From 0e8cf6d9f0ea80b204011c52b9f943ce9eebfcab Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 22 Aug 2024 14:32:05 +0200 Subject: [PATCH 001/136] github workflow for Patmos platform added --- .github/workflows/c-embedded.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/c-embedded.yml b/.github/workflows/c-embedded.yml index f36bf3c73b..20c26019d1 100644 --- a/.github/workflows/c-embedded.yml +++ b/.github/workflows/c-embedded.yml @@ -23,3 +23,7 @@ jobs: # Run the C FlexPRET integration tests. flexpret: uses: ./.github/workflows/c-flexpret-tests.yml + + # Run the C Patmos integration tests. + patmos: + uses: ./.github/workflows/c-patmos-tests.yml From 587ebffaf7415f41722dace5755a172f7122d241 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 22 Aug 2024 14:33:39 +0200 Subject: [PATCH 002/136] github workflow for Patmos platform added 2 --- .github/actions/setup-patmos/action.yml | 17 ++++++++ .github/workflows/c-patmos-tests.yml | 53 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/actions/setup-patmos/action.yml create mode 100644 .github/workflows/c-patmos-tests.yml diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml new file mode 100644 index 0000000000..d640876b9a --- /dev/null +++ b/.github/actions/setup-patmos/action.yml @@ -0,0 +1,17 @@ +name: Install Patmos and dependencies (Linux only) +description: Install Patmos and dependencies (Linux only) +runs: + using: "composite" + steps: + - name: Setup + run: | + # Clone the Patmos repository + mkdir ~/t-crest + cd ~/t-crest + git clone https://github.com/t-crest/patmos-misc.git misc + ./misc/build.sh + + # Save location in PATH + export PATH=$PATH:$HOME/t-crest/misc + shell: bash + diff --git a/.github/workflows/c-patmos-tests.yml b/.github/workflows/c-patmos-tests.yml new file mode 100644 index 0000000000..5cffb01ce9 --- /dev/null +++ b/.github/workflows/c-patmos-tests.yml @@ -0,0 +1,53 @@ +name: C Patmos tests + +on: + workflow_call: + inputs: + compiler-ref: + required: false + type: string + runtime-ref: + required: false + type: string + use-cpp: + required: false + type: boolean + default: false + scheduler: + required: false + type: string + all-platforms: + required: false + default: true + type: boolean + +jobs: + Patmos-tests: + runs-on: ubuntu-latest + steps: + - name: Check out lingua-franca repository + uses: actions/checkout@v3 + with: + repository: lf-lang/lingua-franca + submodules: true + ref: ${{ inputs.compiler-ref }} + fetch-depth: 0 + - name: Prepare build environment + uses: ./.github/actions/prepare-build-env + - name: Setup and build Patmos + uses: ./.github/actions/setup-patmos + - name: Check out specific ref of reactor-c + uses: actions/checkout@v3 + with: + repository: lf-lang/reactor-c + path: core/src/main/resources/lib/c/reactor-c + ref: ${{ inputs.runtime-ref }} + if: ${{ inputs.runtime-ref }} + - name: Run Patmos smoke tests + run: | + rm -rf test/C/src-gen + - name: Report to CodeCov + uses: ./.github/actions/report-code-coverage + with: + files: core/build/reports/jacoco/integrationTestCodeCoverageReport/integrationTestCodeCoverageReport.xml + if: ${{ github.repository == 'lf-lang/lingua-franca' }} From e3cef42339eab54755333353412572f152419373 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 23 Aug 2024 13:31:32 +0200 Subject: [PATCH 003/136] Pushes the RTI image to Docker Hub when the repo owner is lf-lang --- .github/workflows/rti-docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rti-docker.yml b/.github/workflows/rti-docker.yml index e7132ebbbb..5f2cca5b3d 100644 --- a/.github/workflows/rti-docker.yml +++ b/.github/workflows/rti-docker.yml @@ -30,7 +30,7 @@ jobs: latest: false DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - if: ${{ endsWith(env.lf_version, '-snapshot') }} + if: ${{ endsWith(env.lf_version, '-snapshot') && github.repository_owner == 'lf-lang'}} - name: Update latest (released versions only) uses: ./.github/actions/push-rti-docker @@ -39,4 +39,4 @@ jobs: latest: true DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - if: ${{ !endsWith(env.lf_version, '-snapshot') }} + if: ${{ !endsWith(env.lf_version, '-snapshot') && github.repository_owner == 'lf-lang'}} From 2ba7cda5c534fbcbb53f5a2d992dee0fc36ebe2b Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 26 Aug 2024 12:50:40 +0200 Subject: [PATCH 004/136] install needed tools added to setup-patmos/action.yml --- .github/actions/setup-patmos/action.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index d640876b9a..00a5c4c61b 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -5,7 +5,24 @@ runs: steps: - name: Setup run: | + # install needed tools + sudo apt install git openjdk-8-jdk gitk cmake make g++ texinfo flex bison \ + subversion libelf-dev graphviz libboost-dev libboost-program-options-dev ruby-full \ + liblpsolve55-dev zlib1g-dev gtkwave gtkterm scala autoconf libfl2 expect verilator curl + + # install sbt + + sudo apt-get update + sudo apt-get install apt-transport-https curl gnupg -yqq + echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list + echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list + curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo -H gpg --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/scalasbt-release.gpg --import + sudo chmod 644 /etc/apt/trusted.gpg.d/scalasbt-release.gpg + sudo apt-get update + sudo apt-get install sbt + # Clone the Patmos repository + mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc From 55e4323a67cb1cf403f82d487c8411d654546c8f Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 27 Aug 2024 11:52:26 +0200 Subject: [PATCH 005/136] spotless + gitk installation removed --- .github/actions/setup-patmos/action.yml | 9 ++++----- .github/workflows/c-embedded.yml | 2 +- test/C/src/patmos/HelloPatmos.lf | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 00a5c4c61b..3fd4e556d0 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -6,7 +6,7 @@ runs: - name: Setup run: | # install needed tools - sudo apt install git openjdk-8-jdk gitk cmake make g++ texinfo flex bison \ + sudo apt install git openjdk-8-jdk cmake make g++ texinfo flex bison \ subversion libelf-dev graphviz libboost-dev libboost-program-options-dev ruby-full \ liblpsolve55-dev zlib1g-dev gtkwave gtkterm scala autoconf libfl2 expect verilator curl @@ -20,15 +20,14 @@ runs: sudo chmod 644 /etc/apt/trusted.gpg.d/scalasbt-release.gpg sudo apt-get update sudo apt-get install sbt - + # Clone the Patmos repository - + mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc - ./misc/build.sh + ./misc/build.sh # Save location in PATH export PATH=$PATH:$HOME/t-crest/misc shell: bash - diff --git a/.github/workflows/c-embedded.yml b/.github/workflows/c-embedded.yml index 20c26019d1..5b49223589 100644 --- a/.github/workflows/c-embedded.yml +++ b/.github/workflows/c-embedded.yml @@ -24,6 +24,6 @@ jobs: flexpret: uses: ./.github/workflows/c-flexpret-tests.yml - # Run the C Patmos integration tests. + # Run the C Patmos integration tests. patmos: uses: ./.github/workflows/c-patmos-tests.yml diff --git a/test/C/src/patmos/HelloPatmos.lf b/test/C/src/patmos/HelloPatmos.lf index 8f289c980a..48c36c139b 100644 --- a/test/C/src/patmos/HelloPatmos.lf +++ b/test/C/src/patmos/HelloPatmos.lf @@ -1,12 +1,11 @@ target C { - platform: "Patmos", - single-threaded: true, - build-type: Debug, - } - - main reactor { - reaction(startup) {= - printf("Hello World!\n"); - =} - } - \ No newline at end of file + platform: "Patmos", + single-threaded: true, + build-type: Debug +} + +main reactor { + reaction(startup) {= + printf("Hello World!\n"); + =} +} From d5d24cb55209d7855e5ed5ca23bb9ea29895b4f8 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 4 Sep 2024 17:02:42 +0200 Subject: [PATCH 006/136] Spotless --- .../src/main/java/org/lflang/generator/c/CCmakeGenerator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java index c421c3e603..095b18f733 100644 --- a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java @@ -229,7 +229,9 @@ CodeBuilder generateCMakeCode( case PATMOS: cMakeCode.newLine(); cMakeCode.pr("# Include toolchain file and set project"); - cMakeCode.pr("find_program(CLANG_EXECUTABLE NAMES patmos-clang clang DOC \"Path to the clang front-end.\")"); + cMakeCode.pr( + "find_program(CLANG_EXECUTABLE NAMES patmos-clang clang DOC \"Path to the clang" + + " front-end.\")"); cMakeCode.pr("set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE})"); cMakeCode.pr("project(" + executableName + " LANGUAGES C)"); cMakeCode.newLine(); From f58ee50ed7df615385e5d587638204341f6be83a Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sun, 8 Sep 2024 19:05:46 -0700 Subject: [PATCH 007/136] Added angular bracket import for reusable reactors module --- .../src/main/java/org/lflang/LinguaFranca.xtext | 4 +++- core/src/main/java/org/lflang/ast/IsEqual.java | 1 + core/src/main/java/org/lflang/ast/ToLf.java | 3 ++- core/src/main/java/org/lflang/ast/ToSExpr.java | 3 ++- .../org/lflang/scoping/LFScopeProviderImpl.java | 17 ++++++++++++++--- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index ba45b3bd0c..19acb14b47 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -64,7 +64,7 @@ Model: /** * Import declaration. */ -Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; +Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | importPackage=LIB_PATH) ';'?; ReactorDecl: Reactor | ImportedReactor; @@ -431,6 +431,8 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; +terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '>'; + terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; terminal ANY_OTHER: .; diff --git a/core/src/main/java/org/lflang/ast/IsEqual.java b/core/src/main/java/org/lflang/ast/IsEqual.java index 8eec27a430..afe1568f96 100644 --- a/core/src/main/java/org/lflang/ast/IsEqual.java +++ b/core/src/main/java/org/lflang/ast/IsEqual.java @@ -99,6 +99,7 @@ public Boolean caseModel(Model object) { public Boolean caseImport(Import object) { return new ComparisonMachine<>(object, Import.class) .equalAsObjects(Import::getImportURI) + .equalAsObjects(Import::getImportPackage) .listsEquivalent(Import::getReactorClasses) .conclusion; } diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index 3b1b1e48df..dda8524aa7 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -398,7 +398,8 @@ public MalleableString caseImport(Import object) { // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) .append(" from \"") - .append(object.getImportURI()) + // TODO: Check if angular brackets (< >) are required + .append(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()) .append("\"") .get(); } diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index a514d98234..dd013dd9fa 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,8 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - new SAtom<>(object.getImportURI()), + // TODO: Check if angular brackets (< >) are required + new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 3455c1d822..7f55a01ef5 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -26,16 +26,23 @@ package org.lflang.scoping; import static java.util.Collections.emptyList; -import static org.lflang.ast.ASTUtils.*; +import static org.lflang.ast.ASTUtils.allActions; +import static org.lflang.ast.ASTUtils.allInputs; +import static org.lflang.ast.ASTUtils.allOutputs; +import static org.lflang.ast.ASTUtils.allParameters; +import static org.lflang.ast.ASTUtils.allTimers; +import static org.lflang.ast.ASTUtils.allWatchdogs; +import static org.lflang.ast.ASTUtils.toDefinition; -import com.google.inject.Inject; import java.util.ArrayList; + import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.naming.SimpleNameProvider; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; + import org.lflang.lf.Assignment; import org.lflang.lf.Connection; import org.lflang.lf.Deadline; @@ -51,6 +58,8 @@ import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; +import com.google.inject.Inject; + /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, * actions, and timers. Ports can be referenced across at most one level of hierarchy. Parameters, @@ -104,7 +113,9 @@ public IScope getScope(EObject context, EReference reference) { * statement. */ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { - String importURI = ((Import) context.eContainer()).getImportURI(); + String importURI = ((Import) context.eContainer()).getImportURI() != null + ? ((Import) context.eContainer()).getImportURI() + : ((Import) context.eContainer()).getImportPackage().replace("<", "").replace(">", ""); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { From 4319ead4ecebcd85e237309d50bcbd7ea3928f5d Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sun, 8 Sep 2024 19:05:46 -0700 Subject: [PATCH 008/136] Added angular bracket import for reusable reactors module --- .../src/main/java/org/lflang/LinguaFranca.xtext | 4 +++- core/src/main/java/org/lflang/ast/IsEqual.java | 1 + core/src/main/java/org/lflang/ast/ToLf.java | 3 ++- core/src/main/java/org/lflang/ast/ToSExpr.java | 3 ++- .../org/lflang/scoping/LFScopeProviderImpl.java | 17 ++++++++++++++--- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index ba45b3bd0c..19acb14b47 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -64,7 +64,7 @@ Model: /** * Import declaration. */ -Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; +Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | importPackage=LIB_PATH) ';'?; ReactorDecl: Reactor | ImportedReactor; @@ -431,6 +431,8 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; +terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '>'; + terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; terminal ANY_OTHER: .; diff --git a/core/src/main/java/org/lflang/ast/IsEqual.java b/core/src/main/java/org/lflang/ast/IsEqual.java index 8eec27a430..afe1568f96 100644 --- a/core/src/main/java/org/lflang/ast/IsEqual.java +++ b/core/src/main/java/org/lflang/ast/IsEqual.java @@ -99,6 +99,7 @@ public Boolean caseModel(Model object) { public Boolean caseImport(Import object) { return new ComparisonMachine<>(object, Import.class) .equalAsObjects(Import::getImportURI) + .equalAsObjects(Import::getImportPackage) .listsEquivalent(Import::getReactorClasses) .conclusion; } diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index 3b1b1e48df..dda8524aa7 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -398,7 +398,8 @@ public MalleableString caseImport(Import object) { // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) .append(" from \"") - .append(object.getImportURI()) + // TODO: Check if angular brackets (< >) are required + .append(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()) .append("\"") .get(); } diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index a514d98234..dd013dd9fa 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,8 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - new SAtom<>(object.getImportURI()), + // TODO: Check if angular brackets (< >) are required + new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 3455c1d822..7f55a01ef5 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -26,16 +26,23 @@ package org.lflang.scoping; import static java.util.Collections.emptyList; -import static org.lflang.ast.ASTUtils.*; +import static org.lflang.ast.ASTUtils.allActions; +import static org.lflang.ast.ASTUtils.allInputs; +import static org.lflang.ast.ASTUtils.allOutputs; +import static org.lflang.ast.ASTUtils.allParameters; +import static org.lflang.ast.ASTUtils.allTimers; +import static org.lflang.ast.ASTUtils.allWatchdogs; +import static org.lflang.ast.ASTUtils.toDefinition; -import com.google.inject.Inject; import java.util.ArrayList; + import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.naming.SimpleNameProvider; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; + import org.lflang.lf.Assignment; import org.lflang.lf.Connection; import org.lflang.lf.Deadline; @@ -51,6 +58,8 @@ import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; +import com.google.inject.Inject; + /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, * actions, and timers. Ports can be referenced across at most one level of hierarchy. Parameters, @@ -104,7 +113,9 @@ public IScope getScope(EObject context, EReference reference) { * statement. */ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { - String importURI = ((Import) context.eContainer()).getImportURI(); + String importURI = ((Import) context.eContainer()).getImportURI() != null + ? ((Import) context.eContainer()).getImportURI() + : ((Import) context.eContainer()).getImportPackage().replace("<", "").replace(">", ""); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { From bf4ade96723876c577472ffe1944b264c17fa5a8 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 9 Sep 2024 14:17:22 +0200 Subject: [PATCH 009/136] print added to patmos tests --- .github/actions/setup-patmos/action.yml | 2 ++ .github/workflows/c-patmos-tests.yml | 2 ++ core/src/main/resources/lib/c/reactor-c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 3fd4e556d0..05330be7c5 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -3,6 +3,8 @@ description: Install Patmos and dependencies (Linux only) runs: using: "composite" steps: + - name: Print + run: echo "Starting T_CREST Setup" - name: Setup run: | # install needed tools diff --git a/.github/workflows/c-patmos-tests.yml b/.github/workflows/c-patmos-tests.yml index 5cffb01ce9..3431652ba1 100644 --- a/.github/workflows/c-patmos-tests.yml +++ b/.github/workflows/c-patmos-tests.yml @@ -25,6 +25,8 @@ jobs: Patmos-tests: runs-on: ubuntu-latest steps: + - name: Print + run: echo "Patmos Tests Start" - name: Check out lingua-franca repository uses: actions/checkout@v3 with: diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 26cc23b5ee..8d7cfa7394 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 26cc23b5eeb0bd6dcb49b00824e5ae5ac28b3b44 +Subproject commit 8d7cfa73949d3e1d1f39a0c10eb3b2d1d866ce94 From e6f4cbc73d16111feaf1b4ab8e142e567f3b5380 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Mon, 9 Sep 2024 11:46:58 -0700 Subject: [PATCH 010/136] Update core/src/main/java/org/lflang/ast/ToSExpr.java --- core/src/main/java/org/lflang/ast/ToSExpr.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index dd013dd9fa..1a2196d333 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,6 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - // TODO: Check if angular brackets (< >) are required new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } From b571f4cd237d06bdf1385986a2260cc1c37237ba Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 10 Sep 2024 11:11:19 +0200 Subject: [PATCH 011/136] Patmos Category added --- .github/actions/setup-patmos/action.yml | 2 - .github/workflows/c-patmos-tests.yml | 5 +- .../org/lflang/tests/runtime/CPatmosTest.java | 80 +++++++++++++++++++ .../java/org/lflang/tests/Configurators.java | 27 +++++++ 4 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 05330be7c5..3fd4e556d0 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -3,8 +3,6 @@ description: Install Patmos and dependencies (Linux only) runs: using: "composite" steps: - - name: Print - run: echo "Starting T_CREST Setup" - name: Setup run: | # install needed tools diff --git a/.github/workflows/c-patmos-tests.yml b/.github/workflows/c-patmos-tests.yml index 3431652ba1..5dedf58682 100644 --- a/.github/workflows/c-patmos-tests.yml +++ b/.github/workflows/c-patmos-tests.yml @@ -25,8 +25,6 @@ jobs: Patmos-tests: runs-on: ubuntu-latest steps: - - name: Print - run: echo "Patmos Tests Start" - name: Check out lingua-franca repository uses: actions/checkout@v3 with: @@ -47,6 +45,9 @@ jobs: if: ${{ inputs.runtime-ref }} - name: Run Patmos smoke tests run: | + ./gradlew core:integrationTest \ + --tests org.lflang.tests.runtime.CPatmosTest.* \ + core:integrationTestCodeCoverageReport rm -rf test/C/src-gen - name: Report to CodeCov uses: ./.github/actions/report-code-coverage diff --git a/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java new file mode 100644 index 0000000000..3672c15355 --- /dev/null +++ b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java @@ -0,0 +1,80 @@ +/************* + * Copyright (c) 2023, The University of California at Berkeley. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ***************/ +package org.lflang.tests.runtime; + +import java.util.List; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.lflang.target.Target; +import org.lflang.tests.Configurators; +import org.lflang.tests.TestBase; +import org.lflang.tests.TestRegistry.TestCategory; +import org.lflang.tests.Transformers; + +public class CPatmosTest extends TestBase { + + public CPatmosTest() { + super(Target.C); + } + + @Test + public void buildPatmosConcurrent() { + Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); + super.runTestsFor( + List.of(Target.C), + "Build concurrent tests for Patmos.", + TestCategory.CONCURRENT::equals, + Transformers::noChanges, + Configurators::makePatmosCompatible, + TestLevel.BUILD, + false); + } + + @Test + public void buildPatmosBasicTestsUnthreaded() { + Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); + super.runTestsFor( + List.of(Target.C), + "Build basic tests for Patmos in single threaded mode.", + TestCategory.BASIC::equals, + Transformers::noChanges, + Configurators::makePatmosCompatibleUnthreaded, + TestLevel.BUILD, + false); + } + + @Test + public void buildPatmosBasicTests() { + Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); + super.runTestsFor( + List.of(Target.C), + "Build basic tests for Patmos.", + TestCategory.BASIC::equals, + Transformers::noChanges, + Configurators::makePatmosCompatible, + TestLevel.BUILD, + false); + } +} diff --git a/core/src/testFixtures/java/org/lflang/tests/Configurators.java b/core/src/testFixtures/java/org/lflang/tests/Configurators.java index 91522e57bd..aa85b16a90 100644 --- a/core/src/testFixtures/java/org/lflang/tests/Configurators.java +++ b/core/src/testFixtures/java/org/lflang/tests/Configurators.java @@ -132,6 +132,33 @@ public static boolean makeFlexPRETCompatibleUnthreaded(TargetConfig config) { return makeFlexPRETCompatible(config); } + public static boolean makePatmosCompatible(TargetConfig config) { + /** + * Patmos has a maximum of eight hardware threads; override the chosen number of worker threads + * to be 0 (meaning run-time selects it). + * + *

This is to avoid failing tests that have e.g., `workers: 16`. + */ + WorkersProperty.INSTANCE.override(config, 0); + + var platform = config.get(PlatformProperty.INSTANCE); + PlatformProperty.INSTANCE.override( + config, + new PlatformOptions( + Platform.PATMOS, + new Option(true, "emulator"), + platform.port(), + platform.baudRate(), + new Option(true, false), + platform.userThreads())); + return true; + } + + public static boolean makePatmosCompatibleUnthreaded(TargetConfig config) { + disableThreading(config); + return makePatmosCompatible(config); + } + /** * Make no changes to the configuration. * From 21f7b5b5f3962fae570c6e87da399d3b3dfde74f Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 10 Sep 2024 13:11:55 +0200 Subject: [PATCH 012/136] t-crest directory added to the PATH --- .github/actions/setup-patmos/action.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 3fd4e556d0..b99efdb15e 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,12 +22,16 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - + export PATH=\$PATH:\$HOME/t-crest/local/bin mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc ./misc/build.sh + # Make + cd ~/t-crest/llvm/build + make -j + patmos-clang --version # Save location in PATH export PATH=$PATH:$HOME/t-crest/misc shell: bash From 7c3c4f84f968249abe22ba3263eadef8b1eea74b Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 10 Sep 2024 15:43:29 +0200 Subject: [PATCH 013/136] bug fixed --- .github/actions/setup-patmos/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index b99efdb15e..2ce5a9c48c 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,7 +22,7 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - export PATH=\$PATH:\$HOME/t-crest/local/bin + export PATH=$PATH:$HOME/t-crest/local/bin mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc From c25b2f3d7ed5cdc40cb924f0ad73a33de9fb819e Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 13:50:23 -0700 Subject: [PATCH 014/136] Fix bug in ToLf.java; Added test for new import statement --- core/src/main/java/org/lflang/ast/ToLf.java | 6 ++---- test/Python/src/ImportLibrary.lf | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/Python/src/ImportLibrary.lf diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index dda8524aa7..8304cf143a 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -397,10 +397,8 @@ public MalleableString caseImport(Import object) { .append("import ") // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) - .append(" from \"") - // TODO: Check if angular brackets (< >) are required - .append(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()) - .append("\"") + .append(" from ") + .append(object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" : object.getImportPackage()) .get(); } diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf new file mode 100644 index 0000000000..ddb3d5348c --- /dev/null +++ b/test/Python/src/ImportLibrary.lf @@ -0,0 +1,17 @@ +target Python + +import Count from + +reactor Printer { + input i + + reaction(i) {= + print(f"Count: {i.value}") + =} +} + +main reactor { + c = new Count() + p = new Printer() + c.out -> p.i +} From 65762673c550b6ba788f5cff8c3f2bd3976a3825 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 16:30:52 -0700 Subject: [PATCH 015/136] Fix bug in the LinguaFranca.text file --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 19acb14b47..978337f4c3 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -431,7 +431,7 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; -terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '>'; +terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '<' | '>' | '\t' | '\r' | '\n') )* '>'; terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; From 781a55221ed8ab6af518cd06dcedeab2e0fa2206 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 17:04:30 -0700 Subject: [PATCH 016/136] Extend support for new import statements in federated LF programs; Add test case for federated LF program using new imports --- .../federated/generator/FedImportEmitter.java | 16 +++++++++++++--- test/Python/src/FederatedImportLibrary.lf | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/Python/src/FederatedImportLibrary.lf diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 59b2fae58b..72e49c09b9 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -4,7 +4,9 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; + import org.eclipse.emf.ecore.util.EcoreUtil; + import org.lflang.ast.FormattingUtil; import org.lflang.generator.CodeBuilder; import org.lflang.lf.Import; @@ -31,9 +33,17 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .forEach( i -> { visitedImports.add(i); - Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); - i.setImportURI( - fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + if(i.getImportURI() != null) { + Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); + i.setImportURI( + fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + } + else { + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage().replace("<", "").replace(">", "")).toAbsolutePath(); + i.setImportPackage( + "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); + } + }); var importStatements = new CodeBuilder(); diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf new file mode 100644 index 0000000000..88c19dc8d3 --- /dev/null +++ b/test/Python/src/FederatedImportLibrary.lf @@ -0,0 +1,17 @@ +target Python + +import Count from + +reactor Printer { + input i + + reaction(i) {= + print(f"Count: {i.value}") + =} +} + +federated reactor { + c = new Count() + p = new Printer() + c.out -> p.i +} From d8c0ac6fcd0143a46fa2aaf3fbecdf59dbe6527c Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Wed, 11 Sep 2024 16:42:42 -0700 Subject: [PATCH 017/136] Add the new terminal LIB_PATH to Token --- core/src/main/java/org/lflang/LinguaFranca.xtext | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 978337f4c3..709e475baf 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,7 +393,7 @@ SignedInt: ; Literal: - STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean + STRING | CHAR_LIT |SignedFloat | SignedInt | Boolean ; Boolean: @@ -516,7 +516,7 @@ Body: // the end of a target-code segment. Token: // Non-constant terminals - ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | + ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | LIB_PATH | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | // Keywords 'target' | 'import' | 'main' | 'realtime' | 'reactor' | 'state' | 'time' | 'mutable' | 'input' | 'output' | 'timer' | 'action' | 'reaction' | From 88070a226fd1f636fc60af016aaf95d782c203ce Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Wed, 11 Sep 2024 16:44:42 -0700 Subject: [PATCH 018/136] Add the new terminal LIB_PATH to Token --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 709e475baf..af66d4e467 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,7 +393,7 @@ SignedInt: ; Literal: - STRING | CHAR_LIT |SignedFloat | SignedInt | Boolean + STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean ; Boolean: From 5420d2e91f5a310ffdbbe605cd1416f766365ee2 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 12 Sep 2024 14:07:26 +0200 Subject: [PATCH 019/136] REQUIRED added to patmos-clang --- core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java index 095b18f733..adeb178f75 100644 --- a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java @@ -230,7 +230,7 @@ CodeBuilder generateCMakeCode( cMakeCode.newLine(); cMakeCode.pr("# Include toolchain file and set project"); cMakeCode.pr( - "find_program(CLANG_EXECUTABLE NAMES patmos-clang clang DOC \"Path to the clang" + "find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\")"); cMakeCode.pr("set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE})"); cMakeCode.pr("project(" + executableName + " LANGUAGES C)"); From 3466c44e5366f946e3db4fb4f9af49f76a7a638f Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 12 Sep 2024 15:02:29 +0200 Subject: [PATCH 020/136] echo path added --- .github/actions/setup-patmos/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 2ce5a9c48c..5f75daa234 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -23,6 +23,7 @@ runs: # Clone the Patmos repository export PATH=$PATH:$HOME/t-crest/local/bin + echo $PATH mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc From d06856f92717b9383d8787fd55ec27924ae8b065 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 12 Sep 2024 15:37:18 +0200 Subject: [PATCH 021/136] which patmos-clang added --- .github/actions/setup-patmos/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 5f75daa234..0521a5ea1e 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -33,6 +33,7 @@ runs: cd ~/t-crest/llvm/build make -j patmos-clang --version + which patmos-clang # Save location in PATH export PATH=$PATH:$HOME/t-crest/misc shell: bash From 5092b096881fd4e10990c1eb55c3d29abedb8dac Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 13 Sep 2024 12:57:01 +0200 Subject: [PATCH 022/136] save PATH into GITHUB_ENV --- .github/actions/setup-patmos/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 0521a5ea1e..903d9f428b 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,7 +22,7 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - export PATH=$PATH:$HOME/t-crest/local/bin + echo "$PATH:$HOME/t-crest/local/bin" >> $GITHUB_ENV echo $PATH mkdir ~/t-crest cd ~/t-crest @@ -35,5 +35,5 @@ runs: patmos-clang --version which patmos-clang # Save location in PATH - export PATH=$PATH:$HOME/t-crest/misc + echo "$PATH:$HOME/t-crest/misc" >> $GITHUB_ENV shell: bash From c1ac7753d386c7e6f2355f7f124827b8394aebdd Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 13 Sep 2024 14:35:49 +0200 Subject: [PATCH 023/136] is quoted --- .github/actions/setup-patmos/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 903d9f428b..a1bbd0fbbc 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,7 +22,7 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - echo "$PATH:$HOME/t-crest/local/bin" >> $GITHUB_ENV + echo "$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" echo $PATH mkdir ~/t-crest cd ~/t-crest @@ -35,5 +35,5 @@ runs: patmos-clang --version which patmos-clang # Save location in PATH - echo "$PATH:$HOME/t-crest/misc" >> $GITHUB_ENV + echo "$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" shell: bash From ccf962c70f5c212be18f26e912a334be9e4093e5 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 16 Sep 2024 14:25:09 +0200 Subject: [PATCH 024/136] PATH modified and saved in GITHUB_ENV --- .github/actions/setup-patmos/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index a1bbd0fbbc..830a1f849e 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,7 +22,7 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - echo "$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" + echo "PATH=$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" echo $PATH mkdir ~/t-crest cd ~/t-crest @@ -35,5 +35,5 @@ runs: patmos-clang --version which patmos-clang # Save location in PATH - echo "$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" + echo "PATH=$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" shell: bash From 5ffa58c1a44f36731bbe012f1e7ab074d1612405 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 16 Sep 2024 15:12:26 +0200 Subject: [PATCH 025/136] export PATH added along with GITHUB_ENV --- .github/actions/setup-patmos/action.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 830a1f849e..80719c9964 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -22,7 +22,8 @@ runs: sudo apt-get install sbt # Clone the Patmos repository - echo "PATH=$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" + export PATH=$PATH:$HOME/t-crest/local/bin + echo "PATH=\$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" echo $PATH mkdir ~/t-crest cd ~/t-crest @@ -35,5 +36,6 @@ runs: patmos-clang --version which patmos-clang # Save location in PATH - echo "PATH=$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" + export PATH=$PATH:$HOME/t-crest/misc + echo "PATH=\$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" shell: bash From f330ea3dc980978aa18ef2bf0a5da9197444bf9a Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 16 Sep 2024 16:48:17 +0200 Subject: [PATCH 026/136] setting PATH in GITHUB_ENV removed. Some other optional commands removed. --- .github/actions/setup-patmos/action.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 80719c9964..86080d938d 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -23,19 +23,12 @@ runs: # Clone the Patmos repository export PATH=$PATH:$HOME/t-crest/local/bin - echo "PATH=\$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" + echo "$HOME/t-crest/local/bin" >> "$GITHUB_ENV" echo $PATH mkdir ~/t-crest cd ~/t-crest git clone https://github.com/t-crest/patmos-misc.git misc ./misc/build.sh - - # Make - cd ~/t-crest/llvm/build - make -j patmos-clang --version which patmos-clang - # Save location in PATH - export PATH=$PATH:$HOME/t-crest/misc - echo "PATH=\$PATH:$HOME/t-crest/misc" >> "$GITHUB_ENV" shell: bash From 6dafb858fe35a719be98b8407739d645c736dd4a Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Mon, 16 Sep 2024 10:59:43 -0700 Subject: [PATCH 027/136] Resolved conflict in LunguaFranca.xtext by removing the LIB_PATH terminal; Refined importPackage management across affected files --- core/src/main/java/org/lflang/LinguaFranca.xtext | 6 ++---- .../org/lflang/federated/generator/FedImportEmitter.java | 2 +- .../main/java/org/lflang/scoping/LFScopeProviderImpl.java | 2 +- test/Python/src/FederatedImportLibrary.lf | 1 + test/Python/src/ImportLibrary.lf | 1 + 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index af66d4e467..b34c5be13d 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -64,7 +64,7 @@ Model: /** * Import declaration. */ -Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | importPackage=LIB_PATH) ';'?; +Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | '<' importPackage=Path '>') ';'?; ReactorDecl: Reactor | ImportedReactor; @@ -431,8 +431,6 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; -terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '<' | '>' | '\t' | '\r' | '\n') )* '>'; - terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; terminal ANY_OTHER: .; @@ -516,7 +514,7 @@ Body: // the end of a target-code segment. Token: // Non-constant terminals - ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | LIB_PATH | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | + ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | // Keywords 'target' | 'import' | 'main' | 'realtime' | 'reactor' | 'state' | 'time' | 'mutable' | 'input' | 'output' | 'timer' | 'action' | 'reaction' | diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 72e49c09b9..f3ac953e73 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -39,7 +39,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); } else { - Path importPath = fileConfig.srcPath.resolve(i.getImportPackage().replace("<", "").replace(">", "")).toAbsolutePath(); + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); i.setImportPackage( "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 7f55a01ef5..f39b64146b 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -115,7 +115,7 @@ public IScope getScope(EObject context, EReference reference) { protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { String importURI = ((Import) context.eContainer()).getImportURI() != null ? ((Import) context.eContainer()).getImportURI() - : ((Import) context.eContainer()).getImportPackage().replace("<", "").replace(">", ""); + : ((Import) context.eContainer()).getImportPackage(); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index 88c19dc8d3..c5ac273da4 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,3 +1,4 @@ +# Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs target Python import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index ddb3d5348c..5c98680ddb 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,3 +1,4 @@ +# Test the new import statement with the import path enclosed in angle brackets target Python import Count from From 5c8dd4edaa2cf4777bb0539139c01020d9315075 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Mon, 16 Sep 2024 14:56:01 -0700 Subject: [PATCH 028/136] Corrected formatting and updated import statements for generated files in federated LF programs --- core/src/main/java/org/lflang/ast/ToLf.java | 5 ++++- .../src/main/java/org/lflang/ast/ToSExpr.java | 3 ++- .../federated/generator/FedImportEmitter.java | 20 ++++++++----------- .../lflang/scoping/LFScopeProviderImpl.java | 7 ++++--- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index 8304cf143a..da23c44560 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -398,7 +398,10 @@ public MalleableString caseImport(Import object) { // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) .append(" from ") - .append(object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" : object.getImportPackage()) + .append( + object.getImportURI() != null + ? "\"" + object.getImportURI() + "\"" + : object.getImportPackage()) .get(); } diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index 1a2196d333..a2047f5280 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,8 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), + new SAtom<>( + object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index f3ac953e73..2f0fbd3c43 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -4,9 +4,7 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; - import org.eclipse.emf.ecore.util.EcoreUtil; - import org.lflang.ast.FormattingUtil; import org.lflang.generator.CodeBuilder; import org.lflang.lf.Import; @@ -33,17 +31,15 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .forEach( i -> { visitedImports.add(i); - if(i.getImportURI() != null) { - Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); - i.setImportURI( - fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + if (i.getImportURI() != null) { + Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); + i.setImportURI( + fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + } else { + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); + i.setImportPackage( + "\"" + fileConfig.getSrcPath().relativize(importPath).toString() + "\""); } - else { - Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); - i.setImportPackage( - "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); - } - }); var importStatements = new CodeBuilder(); diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index f39b64146b..3f9032dc8d 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -113,9 +113,10 @@ public IScope getScope(EObject context, EReference reference) { * statement. */ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { - String importURI = ((Import) context.eContainer()).getImportURI() != null - ? ((Import) context.eContainer()).getImportURI() - : ((Import) context.eContainer()).getImportPackage(); + String importURI = + ((Import) context.eContainer()).getImportURI() != null + ? ((Import) context.eContainer()).getImportURI() + : ((Import) context.eContainer()).getImportPackage(); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { From f8d1e8352e0b02a1908e587058370bc9f900d4f9 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 17 Sep 2024 11:13:04 +0200 Subject: [PATCH 029/136] setting PATH in GITHUB_ENV returned without backslash --- .github/actions/setup-patmos/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-patmos/action.yml b/.github/actions/setup-patmos/action.yml index 86080d938d..7ecc47a67e 100644 --- a/.github/actions/setup-patmos/action.yml +++ b/.github/actions/setup-patmos/action.yml @@ -23,7 +23,7 @@ runs: # Clone the Patmos repository export PATH=$PATH:$HOME/t-crest/local/bin - echo "$HOME/t-crest/local/bin" >> "$GITHUB_ENV" + echo "PATH=$PATH:$HOME/t-crest/local/bin" >> "$GITHUB_ENV" echo $PATH mkdir ~/t-crest cd ~/t-crest From e3ce6cf854bc6fb0ed0d53b24ddff25658825473 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 18:13:19 -0700 Subject: [PATCH 030/136] Solved formatting error --- core/src/main/java/org/lflang/ast/ToLf.java | 2 +- .../main/java/org/lflang/scoping/LFScopeProviderImpl.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index da23c44560..5f32920d9b 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -401,7 +401,7 @@ public MalleableString caseImport(Import object) { .append( object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" - : object.getImportPackage()) + : "<" + object.getImportPackage() + ">") .get(); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 3f9032dc8d..87650dd212 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -34,15 +34,14 @@ import static org.lflang.ast.ASTUtils.allWatchdogs; import static org.lflang.ast.ASTUtils.toDefinition; +import com.google.inject.Inject; import java.util.ArrayList; - import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.naming.SimpleNameProvider; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; - import org.lflang.lf.Assignment; import org.lflang.lf.Connection; import org.lflang.lf.Deadline; @@ -58,8 +57,6 @@ import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; -import com.google.inject.Inject; - /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, * actions, and timers. Ports can be referenced across at most one level of hierarchy. Parameters, From f05c567cf7ad9503c52d11af09520b5a6ccb367e Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 19:10:40 -0700 Subject: [PATCH 031/136] Removed quotes in setImportPackage --- .../java/org/lflang/federated/generator/FedImportEmitter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 2f0fbd3c43..9022f6ae4e 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -38,7 +38,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi } else { Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); i.setImportPackage( - "\"" + fileConfig.getSrcPath().relativize(importPath).toString() + "\""); + fileConfig.getSrcPath().relativize(importPath).toString()); } }); From ab4391bbbfc1f611713d3bc60feb23593260932a Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 19:28:52 -0700 Subject: [PATCH 032/136] Fix format --- .../java/org/lflang/federated/generator/FedImportEmitter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 9022f6ae4e..e4cc0f276d 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -37,8 +37,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); } else { Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); - i.setImportPackage( - fileConfig.getSrcPath().relativize(importPath).toString()); + i.setImportPackage(fileConfig.getSrcPath().relativize(importPath).toString()); } }); From c36bf05c5d02c76f0784f1f2530ea829dc27748a Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 20:11:51 -0700 Subject: [PATCH 033/136] Enhanced tests for new import statement --- test/Python/src/FederatedImportLibrary.lf | 4 +++- test/Python/src/ImportLibrary.lf | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index c5ac273da4..a7aefe1f47 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,5 +1,7 @@ # Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs -target Python +target Python { + timeout: 2 sec +} import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index 5c98680ddb..5f98f750b4 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,5 +1,7 @@ # Test the new import statement with the import path enclosed in angle brackets -target Python +target Python { + timeout: 2 sec +} import Count from From 3da89fc8f3ff941a04a9ff4d9abdc369cab49444 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 20:21:22 -0700 Subject: [PATCH 034/136] Enhanced tests for new import statement; Fix formatting --- test/Python/src/FederatedImportLibrary.lf | 2 +- test/Python/src/ImportLibrary.lf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index a7aefe1f47..17d500aa93 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,6 +1,6 @@ # Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs target Python { - timeout: 2 sec + timeout: 2 sec } import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index 5f98f750b4..962a616a6b 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,6 +1,6 @@ # Test the new import statement with the import path enclosed in angle brackets target Python { - timeout: 2 sec + timeout: 2 sec } import Count from From 9af3158f6186b841c6def36305b2da9bb714f0c0 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sun, 8 Sep 2024 19:05:46 -0700 Subject: [PATCH 035/136] Added angular bracket import for reusable reactors module --- .../src/main/java/org/lflang/LinguaFranca.xtext | 4 +++- core/src/main/java/org/lflang/ast/IsEqual.java | 1 + core/src/main/java/org/lflang/ast/ToLf.java | 3 ++- core/src/main/java/org/lflang/ast/ToSExpr.java | 3 ++- .../org/lflang/scoping/LFScopeProviderImpl.java | 17 ++++++++++++++--- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index ba45b3bd0c..19acb14b47 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -64,7 +64,7 @@ Model: /** * Import declaration. */ -Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; +Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | importPackage=LIB_PATH) ';'?; ReactorDecl: Reactor | ImportedReactor; @@ -431,6 +431,8 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; +terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '>'; + terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; terminal ANY_OTHER: .; diff --git a/core/src/main/java/org/lflang/ast/IsEqual.java b/core/src/main/java/org/lflang/ast/IsEqual.java index 8eec27a430..afe1568f96 100644 --- a/core/src/main/java/org/lflang/ast/IsEqual.java +++ b/core/src/main/java/org/lflang/ast/IsEqual.java @@ -99,6 +99,7 @@ public Boolean caseModel(Model object) { public Boolean caseImport(Import object) { return new ComparisonMachine<>(object, Import.class) .equalAsObjects(Import::getImportURI) + .equalAsObjects(Import::getImportPackage) .listsEquivalent(Import::getReactorClasses) .conclusion; } diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index 3b1b1e48df..dda8524aa7 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -398,7 +398,8 @@ public MalleableString caseImport(Import object) { // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) .append(" from \"") - .append(object.getImportURI()) + // TODO: Check if angular brackets (< >) are required + .append(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()) .append("\"") .get(); } diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index a514d98234..dd013dd9fa 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,8 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - new SAtom<>(object.getImportURI()), + // TODO: Check if angular brackets (< >) are required + new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 3455c1d822..7f55a01ef5 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -26,16 +26,23 @@ package org.lflang.scoping; import static java.util.Collections.emptyList; -import static org.lflang.ast.ASTUtils.*; +import static org.lflang.ast.ASTUtils.allActions; +import static org.lflang.ast.ASTUtils.allInputs; +import static org.lflang.ast.ASTUtils.allOutputs; +import static org.lflang.ast.ASTUtils.allParameters; +import static org.lflang.ast.ASTUtils.allTimers; +import static org.lflang.ast.ASTUtils.allWatchdogs; +import static org.lflang.ast.ASTUtils.toDefinition; -import com.google.inject.Inject; import java.util.ArrayList; + import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.naming.SimpleNameProvider; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; + import org.lflang.lf.Assignment; import org.lflang.lf.Connection; import org.lflang.lf.Deadline; @@ -51,6 +58,8 @@ import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; +import com.google.inject.Inject; + /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, * actions, and timers. Ports can be referenced across at most one level of hierarchy. Parameters, @@ -104,7 +113,9 @@ public IScope getScope(EObject context, EReference reference) { * statement. */ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { - String importURI = ((Import) context.eContainer()).getImportURI(); + String importURI = ((Import) context.eContainer()).getImportURI() != null + ? ((Import) context.eContainer()).getImportURI() + : ((Import) context.eContainer()).getImportPackage().replace("<", "").replace(">", ""); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { From 5ec94228c474c8f0f5c2b8ec53025a03cde10ed0 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Mon, 9 Sep 2024 11:46:58 -0700 Subject: [PATCH 036/136] Update core/src/main/java/org/lflang/ast/ToSExpr.java --- core/src/main/java/org/lflang/ast/ToSExpr.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index dd013dd9fa..1a2196d333 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,6 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - // TODO: Check if angular brackets (< >) are required new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } From 95366ab484bc4333c997fe5a4d2f7f98d1fb4797 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 13:50:23 -0700 Subject: [PATCH 037/136] Fix bug in ToLf.java; Added test for new import statement --- core/src/main/java/org/lflang/ast/ToLf.java | 6 ++---- test/Python/src/ImportLibrary.lf | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 test/Python/src/ImportLibrary.lf diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index dda8524aa7..8304cf143a 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -397,10 +397,8 @@ public MalleableString caseImport(Import object) { .append("import ") // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) - .append(" from \"") - // TODO: Check if angular brackets (< >) are required - .append(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()) - .append("\"") + .append(" from ") + .append(object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" : object.getImportPackage()) .get(); } diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf new file mode 100644 index 0000000000..ddb3d5348c --- /dev/null +++ b/test/Python/src/ImportLibrary.lf @@ -0,0 +1,17 @@ +target Python + +import Count from + +reactor Printer { + input i + + reaction(i) {= + print(f"Count: {i.value}") + =} +} + +main reactor { + c = new Count() + p = new Printer() + c.out -> p.i +} From aab992df10497d9cce7e40bd358cb6e06fcfc5a6 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 16:30:52 -0700 Subject: [PATCH 038/136] Fix bug in the LinguaFranca.text file --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 19acb14b47..978337f4c3 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -431,7 +431,7 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; -terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '>'; +terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '<' | '>' | '\t' | '\r' | '\n') )* '>'; terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; From fabf6b559e59cb45047e480f80454ff5e121a615 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 10 Sep 2024 17:04:30 -0700 Subject: [PATCH 039/136] Extend support for new import statements in federated LF programs; Add test case for federated LF program using new imports --- .../federated/generator/FedImportEmitter.java | 16 +++++++++++++--- test/Python/src/FederatedImportLibrary.lf | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/Python/src/FederatedImportLibrary.lf diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 59b2fae58b..72e49c09b9 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -4,7 +4,9 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; + import org.eclipse.emf.ecore.util.EcoreUtil; + import org.lflang.ast.FormattingUtil; import org.lflang.generator.CodeBuilder; import org.lflang.lf.Import; @@ -31,9 +33,17 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .forEach( i -> { visitedImports.add(i); - Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); - i.setImportURI( - fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + if(i.getImportURI() != null) { + Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); + i.setImportURI( + fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + } + else { + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage().replace("<", "").replace(">", "")).toAbsolutePath(); + i.setImportPackage( + "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); + } + }); var importStatements = new CodeBuilder(); diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf new file mode 100644 index 0000000000..88c19dc8d3 --- /dev/null +++ b/test/Python/src/FederatedImportLibrary.lf @@ -0,0 +1,17 @@ +target Python + +import Count from + +reactor Printer { + input i + + reaction(i) {= + print(f"Count: {i.value}") + =} +} + +federated reactor { + c = new Count() + p = new Printer() + c.out -> p.i +} From 031ac4e9c02e994996ea06dbb4f9ae2d804cb736 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Wed, 11 Sep 2024 16:42:42 -0700 Subject: [PATCH 040/136] Add the new terminal LIB_PATH to Token --- core/src/main/java/org/lflang/LinguaFranca.xtext | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 978337f4c3..709e475baf 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,7 +393,7 @@ SignedInt: ; Literal: - STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean + STRING | CHAR_LIT |SignedFloat | SignedInt | Boolean ; Boolean: @@ -516,7 +516,7 @@ Body: // the end of a target-code segment. Token: // Non-constant terminals - ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | + ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | LIB_PATH | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | // Keywords 'target' | 'import' | 'main' | 'realtime' | 'reactor' | 'state' | 'time' | 'mutable' | 'input' | 'output' | 'timer' | 'action' | 'reaction' | From 82ccc7f21d22218e5a92e3e36deb8f51dafe2037 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Wed, 11 Sep 2024 16:44:42 -0700 Subject: [PATCH 041/136] Add the new terminal LIB_PATH to Token --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 709e475baf..af66d4e467 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,7 +393,7 @@ SignedInt: ; Literal: - STRING | CHAR_LIT |SignedFloat | SignedInt | Boolean + STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean ; Boolean: From 5ac1d15f752f2a43d47ede59759743c799d55795 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Mon, 16 Sep 2024 10:59:43 -0700 Subject: [PATCH 042/136] Resolved conflict in LunguaFranca.xtext by removing the LIB_PATH terminal; Refined importPackage management across affected files --- core/src/main/java/org/lflang/LinguaFranca.xtext | 6 ++---- .../org/lflang/federated/generator/FedImportEmitter.java | 2 +- .../main/java/org/lflang/scoping/LFScopeProviderImpl.java | 2 +- test/Python/src/FederatedImportLibrary.lf | 1 + test/Python/src/ImportLibrary.lf | 1 + 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index af66d4e467..b34c5be13d 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -64,7 +64,7 @@ Model: /** * Import declaration. */ -Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | importPackage=LIB_PATH) ';'?; +Import: 'import' reactorClasses+=ImportedReactor (',' reactorClasses+=ImportedReactor)* 'from' (importURI=STRING | '<' importPackage=Path '>') ';'?; ReactorDecl: Reactor | ImportedReactor; @@ -431,8 +431,6 @@ terminal STRING: '"' ( '\\' . | !('\\' | '"' | '\t' | '\r' | '\n') )* '"' | '"""' -> '"""' ; -terminal LIB_PATH: '<' ( '\\' . | !('\\' | '"' | '<' | '>' | '\t' | '\r' | '\n') )* '>'; - terminal CHAR_LIT: "'" ( '\\' . | !('\\' | "'" | '\t' | '\r' | '\n') ) "'"; terminal ANY_OTHER: .; @@ -516,7 +514,7 @@ Body: // the end of a target-code segment. Token: // Non-constant terminals - ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | LIB_PATH | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | + ID | INT | FLOAT_EXP_SUFFIX | LT_ANNOT | CPP_RAW_STR | STRING | CHAR_LIT | ML_COMMENT | SL_COMMENT | WS | ANY_OTHER | // Keywords 'target' | 'import' | 'main' | 'realtime' | 'reactor' | 'state' | 'time' | 'mutable' | 'input' | 'output' | 'timer' | 'action' | 'reaction' | diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 72e49c09b9..f3ac953e73 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -39,7 +39,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); } else { - Path importPath = fileConfig.srcPath.resolve(i.getImportPackage().replace("<", "").replace(">", "")).toAbsolutePath(); + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); i.setImportPackage( "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 7f55a01ef5..f39b64146b 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -115,7 +115,7 @@ public IScope getScope(EObject context, EReference reference) { protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { String importURI = ((Import) context.eContainer()).getImportURI() != null ? ((Import) context.eContainer()).getImportURI() - : ((Import) context.eContainer()).getImportPackage().replace("<", "").replace(">", ""); + : ((Import) context.eContainer()).getImportPackage(); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index 88c19dc8d3..c5ac273da4 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,3 +1,4 @@ +# Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs target Python import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index ddb3d5348c..5c98680ddb 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,3 +1,4 @@ +# Test the new import statement with the import path enclosed in angle brackets target Python import Count from From 52cfaf6c406a1d7d988f23f1dfa1c08120dff7bc Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Mon, 16 Sep 2024 14:56:01 -0700 Subject: [PATCH 043/136] Corrected formatting and updated import statements for generated files in federated LF programs --- core/src/main/java/org/lflang/ast/ToLf.java | 5 ++++- .../src/main/java/org/lflang/ast/ToSExpr.java | 3 ++- .../federated/generator/FedImportEmitter.java | 20 ++++++++----------- .../lflang/scoping/LFScopeProviderImpl.java | 7 ++++--- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index 8304cf143a..da23c44560 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -398,7 +398,10 @@ public MalleableString caseImport(Import object) { // TODO: This is a place where we can use conditional parentheses. .append(list(", ", "", "", false, true, true, object.getReactorClasses())) .append(" from ") - .append(object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" : object.getImportPackage()) + .append( + object.getImportURI() != null + ? "\"" + object.getImportURI() + "\"" + : object.getImportPackage()) .get(); } diff --git a/core/src/main/java/org/lflang/ast/ToSExpr.java b/core/src/main/java/org/lflang/ast/ToSExpr.java index 1a2196d333..a2047f5280 100644 --- a/core/src/main/java/org/lflang/ast/ToSExpr.java +++ b/core/src/main/java/org/lflang/ast/ToSExpr.java @@ -217,7 +217,8 @@ public SExpr caseImport(Import object) { // reactorClasses+=ImportedReactor)* 'from' importURI=STRING ';'?; return sList( "import", - new SAtom<>(object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), + new SAtom<>( + object.getImportURI() != null ? object.getImportURI() : object.getImportPackage()), sList("reactors", object.getReactorClasses())); } diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index f3ac953e73..2f0fbd3c43 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -4,9 +4,7 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; - import org.eclipse.emf.ecore.util.EcoreUtil; - import org.lflang.ast.FormattingUtil; import org.lflang.generator.CodeBuilder; import org.lflang.lf.Import; @@ -33,17 +31,15 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .forEach( i -> { visitedImports.add(i); - if(i.getImportURI() != null) { - Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); - i.setImportURI( - fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + if (i.getImportURI() != null) { + Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); + i.setImportURI( + fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); + } else { + Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); + i.setImportPackage( + "\"" + fileConfig.getSrcPath().relativize(importPath).toString() + "\""); } - else { - Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); - i.setImportPackage( - "<" + fileConfig.getSrcPath().relativize(importPath).toString() + ">"); - } - }); var importStatements = new CodeBuilder(); diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index f39b64146b..3f9032dc8d 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -113,9 +113,10 @@ public IScope getScope(EObject context, EReference reference) { * statement. */ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference reference) { - String importURI = ((Import) context.eContainer()).getImportURI() != null - ? ((Import) context.eContainer()).getImportURI() - : ((Import) context.eContainer()).getImportPackage(); + String importURI = + ((Import) context.eContainer()).getImportURI() != null + ? ((Import) context.eContainer()).getImportURI() + : ((Import) context.eContainer()).getImportPackage(); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { From fe878a5672e5d3c9a1c183edc6823db6397790e2 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 18:13:19 -0700 Subject: [PATCH 044/136] Solved formatting error --- core/src/main/java/org/lflang/ast/ToLf.java | 2 +- .../main/java/org/lflang/scoping/LFScopeProviderImpl.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ToLf.java b/core/src/main/java/org/lflang/ast/ToLf.java index da23c44560..5f32920d9b 100644 --- a/core/src/main/java/org/lflang/ast/ToLf.java +++ b/core/src/main/java/org/lflang/ast/ToLf.java @@ -401,7 +401,7 @@ public MalleableString caseImport(Import object) { .append( object.getImportURI() != null ? "\"" + object.getImportURI() + "\"" - : object.getImportPackage()) + : "<" + object.getImportPackage() + ">") .get(); } diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 3f9032dc8d..87650dd212 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -34,15 +34,14 @@ import static org.lflang.ast.ASTUtils.allWatchdogs; import static org.lflang.ast.ASTUtils.toDefinition; +import com.google.inject.Inject; import java.util.ArrayList; - import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.xtext.naming.SimpleNameProvider; import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.Scopes; import org.eclipse.xtext.scoping.impl.SelectableBasedScope; - import org.lflang.lf.Assignment; import org.lflang.lf.Connection; import org.lflang.lf.Deadline; @@ -58,8 +57,6 @@ import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; -import com.google.inject.Inject; - /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, * actions, and timers. Ports can be referenced across at most one level of hierarchy. Parameters, From 3dadae8ce1fe5b54884dfc35e9b0eca18548a345 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 19:10:40 -0700 Subject: [PATCH 045/136] Removed quotes in setImportPackage --- .../java/org/lflang/federated/generator/FedImportEmitter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 2f0fbd3c43..9022f6ae4e 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -38,7 +38,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi } else { Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); i.setImportPackage( - "\"" + fileConfig.getSrcPath().relativize(importPath).toString() + "\""); + fileConfig.getSrcPath().relativize(importPath).toString()); } }); From 63457326a1c55a7280d75b170d4a4ef1c3080e31 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 19:28:52 -0700 Subject: [PATCH 046/136] Fix format --- .../java/org/lflang/federated/generator/FedImportEmitter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 9022f6ae4e..e4cc0f276d 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -37,8 +37,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); } else { Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); - i.setImportPackage( - fileConfig.getSrcPath().relativize(importPath).toString()); + i.setImportPackage(fileConfig.getSrcPath().relativize(importPath).toString()); } }); From feee84be5d2ac4cf40e59bc33c2408a520f096c5 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 20:11:51 -0700 Subject: [PATCH 047/136] Enhanced tests for new import statement --- test/Python/src/FederatedImportLibrary.lf | 4 +++- test/Python/src/ImportLibrary.lf | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index c5ac273da4..a7aefe1f47 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,5 +1,7 @@ # Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs -target Python +target Python { + timeout: 2 sec +} import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index 5c98680ddb..5f98f750b4 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,5 +1,7 @@ # Test the new import statement with the import path enclosed in angle brackets -target Python +target Python { + timeout: 2 sec +} import Count from From 338726ebaba87468530fa5a089e54e27bfb0064d Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 17 Sep 2024 20:21:22 -0700 Subject: [PATCH 048/136] Enhanced tests for new import statement; Fix formatting --- test/Python/src/FederatedImportLibrary.lf | 2 +- test/Python/src/ImportLibrary.lf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf index a7aefe1f47..17d500aa93 100644 --- a/test/Python/src/FederatedImportLibrary.lf +++ b/test/Python/src/FederatedImportLibrary.lf @@ -1,6 +1,6 @@ # Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs target Python { - timeout: 2 sec + timeout: 2 sec } import Count from diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf index 5f98f750b4..962a616a6b 100644 --- a/test/Python/src/ImportLibrary.lf +++ b/test/Python/src/ImportLibrary.lf @@ -1,6 +1,6 @@ # Test the new import statement with the import path enclosed in angle brackets target Python { - timeout: 2 sec + timeout: 2 sec } import Count from From 67be8686f684c1c6c0bbfcdb36ba5c34e72b10a1 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 24 Sep 2024 15:26:16 -0700 Subject: [PATCH 049/136] =?UTF-8?q?Added=20full=20support=20for=20the=20ne?= =?UTF-8?q?w=20import=20statement=20structure=20for=20Lingo=20libraries=20?= =?UTF-8?q?(=E2=80=98=E2=80=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lflang/LFResourceDescriptionStrategy.java | 13 ++- .../main/java/org/lflang/LinguaFranca.xtext | 2 +- .../federated/generator/FedImportEmitter.java | 20 ++-- .../lflang/scoping/LFGlobalScopeProvider.java | 2 +- .../lflang/scoping/LFScopeProviderImpl.java | 4 +- .../main/java/org/lflang/util/ImportUtil.java | 99 +++++++++++++++++++ test/Python/src/FederatedImportLibrary.lf | 20 ---- test/Python/src/ImportLibrary.lf | 20 ---- .../FederatedTestImportPackages.lf | 20 ++++ .../src/lingo_imports/TestImportPackages.lf | 20 ++++ .../library-test/src/lib/Import.lf | 12 +++ 11 files changed, 180 insertions(+), 52 deletions(-) create mode 100644 core/src/main/java/org/lflang/util/ImportUtil.java delete mode 100644 test/Python/src/FederatedImportLibrary.lf delete mode 100644 test/Python/src/ImportLibrary.lf create mode 100644 test/Python/src/lingo_imports/FederatedTestImportPackages.lf create mode 100644 test/Python/src/lingo_imports/TestImportPackages.lf create mode 100644 test/Python/target/lfc_include/library-test/src/lib/Import.lf diff --git a/core/src/main/java/org/lflang/LFResourceDescriptionStrategy.java b/core/src/main/java/org/lflang/LFResourceDescriptionStrategy.java index 487e63374b..db055a7df8 100644 --- a/core/src/main/java/org/lflang/LFResourceDescriptionStrategy.java +++ b/core/src/main/java/org/lflang/LFResourceDescriptionStrategy.java @@ -35,6 +35,7 @@ import org.eclipse.xtext.scoping.impl.ImportUriResolver; import org.eclipse.xtext.util.IAcceptor; import org.lflang.lf.Model; +import org.lflang.util.ImportUtil; /** * Resource description strategy designed to limit global scope to only those files that were @@ -77,7 +78,17 @@ public boolean createEObjectDescriptions( */ private void createEObjectDescriptionForModel( Model model, IAcceptor acceptor) { - var uris = model.getImports().stream().map(uriResolver).collect(Collectors.joining(DELIMITER)); + var uris = + model.getImports().stream() + .map( + importObj -> { + return (importObj.getImportURI() != null) + ? importObj.getImportURI() + : ImportUtil.buildPackageURI( + importObj.getImportPackage(), + model.eResource()); // Use the resolved import string + }) + .collect(Collectors.joining(DELIMITER)); var userData = Map.of(INCLUDES, uris); QualifiedName qname = QualifiedName.create(model.eResource().getURI().toString()); acceptor.accept(EObjectDescription.create(qname, model, userData)); diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index b34c5be13d..a52f9fec23 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -478,7 +478,7 @@ Code: ; FSName: - (ID | '.' | '_')+ + (ID | '.' | '_' | '-')+ ; // Absolute or relative directory path in Windows, Linux, or MacOS. Path: diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index e4cc0f276d..8ffe120af1 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -9,6 +9,7 @@ import org.lflang.generator.CodeBuilder; import org.lflang.lf.Import; import org.lflang.lf.Model; +import org.lflang.util.ImportUtil; /** * Helper class to generate import statements for a federate. @@ -31,14 +32,17 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .forEach( i -> { visitedImports.add(i); - if (i.getImportURI() != null) { - Path importPath = fileConfig.srcPath.resolve(i.getImportURI()).toAbsolutePath(); - i.setImportURI( - fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); - } else { - Path importPath = fileConfig.srcPath.resolve(i.getImportPackage()).toAbsolutePath(); - i.setImportPackage(fileConfig.getSrcPath().relativize(importPath).toString()); - } + Path importPath = + fileConfig + .srcPath + .resolve( + i.getImportURI() != null + ? i.getImportURI() + : ImportUtil.buildPackageURIfromSrc( + i.getImportPackage(), fileConfig.srcPath.toString())) + .toAbsolutePath(); + i.setImportURI( + fileConfig.getSrcPath().relativize(importPath).toString().replace('\\', '/')); }); var importStatements = new CodeBuilder(); diff --git a/core/src/main/java/org/lflang/scoping/LFGlobalScopeProvider.java b/core/src/main/java/org/lflang/scoping/LFGlobalScopeProvider.java index 18c7a3a8af..6c58f67665 100644 --- a/core/src/main/java/org/lflang/scoping/LFGlobalScopeProvider.java +++ b/core/src/main/java/org/lflang/scoping/LFGlobalScopeProvider.java @@ -39,7 +39,7 @@ /** * Global scope provider that limits access to only those files that were explicitly imported. * - *

Adapted from from Xtext manual, Chapter 8.7. + *

Adapted from Xtext manual, Chapter 8.7. * * @author Marten Lohstroh * @see xtext diff --git a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java index 87650dd212..e45c25137c 100644 --- a/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java +++ b/core/src/main/java/org/lflang/scoping/LFScopeProviderImpl.java @@ -56,6 +56,7 @@ import org.lflang.lf.ReactorDecl; import org.lflang.lf.VarRef; import org.lflang.lf.Watchdog; +import org.lflang.util.ImportUtil; /** * This class enforces custom rules. In particular, it resolves references to parameters, ports, @@ -113,7 +114,8 @@ protected IScope getScopeForImportedReactor(ImportedReactor context, EReference String importURI = ((Import) context.eContainer()).getImportURI() != null ? ((Import) context.eContainer()).getImportURI() - : ((Import) context.eContainer()).getImportPackage(); + : ImportUtil.buildPackageURI( + ((Import) context.eContainer()).getImportPackage(), context.eResource()); var importedURI = scopeProvider.resolve(importURI == null ? "" : importURI, context.eResource()); if (importedURI != null) { diff --git a/core/src/main/java/org/lflang/util/ImportUtil.java b/core/src/main/java/org/lflang/util/ImportUtil.java new file mode 100644 index 0000000000..ef52e39e5f --- /dev/null +++ b/core/src/main/java/org/lflang/util/ImportUtil.java @@ -0,0 +1,99 @@ +package org.lflang.util; + +import java.nio.file.Path; +import java.nio.file.Paths; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; + +/** + * Utility class for handling package-related URIs in the context of LF (Lingua Franca) libraries. + * This class provides methods to build URIs for accessing library files based on their location in + * a project structure, specifically targeting the "target/lfc_include" directory for library + * inclusion. + */ +public class ImportUtil { + + /** + * Builds a package URI based on the provided URI string and resource. It traverses upwards from + * the current resource URI until it finds the "src/" directory, then constructs the final URI + * pointing to the library file within the "target/lfc_include" directory. + * + * @param uriStr A string representing the URI of the file. It must contain both the library name + * and file name, separated by a '/'. + * @param resource The resource from which the URI resolution should start. + * @return The constructed package URI as a string. + * @throws IllegalArgumentException if the URI string does not contain both library and file + * names. + */ + public static String buildPackageURI(String uriStr, Resource resource) { + URI currentURI = URI.createURI("."); + URI rootURI = currentURI.resolve(resource.getURI()); + StringBuilder pathBuilder = new StringBuilder(); + + String[] uriParts = uriStr.split("/"); + + if (uriParts.length < 2) { + throw new IllegalArgumentException("URI must contain both library name and file name."); + } + + // Traverse upwards until we reach the "src/" directory + while (!rootURI.toString().endsWith("src/")) { + currentURI = URI.createURI(".."); + rootURI = currentURI.resolve(resource.getURI()); + pathBuilder.append("../"); + } + + pathBuilder + .append("../target/lfc_include/") + .append(uriParts[0]) + .append("/src/lib/") + .append(uriParts[1]); + + return pathBuilder.toString(); + } + + /** + * Builds a package URI based on the provided URI string and source path. This method works + * similarly to the `buildPackageURI`, but it accepts a direct source path instead of a resource. + * It traverses upwards to locate the "src/" directory and then constructs the URI pointing to the + * library file. + * + * @param uriStr A string representing the URI of the file. It must contain both the library name + * and file name, separated by a '/'. + * @param src The source path from which the URI resolution should start. + * @return The constructed package URI as a string. + * @throws IllegalArgumentException if the URI string or source path is null, empty, or does not + * contain both the library name and file name. + */ + public static String buildPackageURIfromSrc(String uriStr, String src) { + if (uriStr == null || src == null || uriStr.trim().isEmpty() || src.trim().isEmpty()) { + throw new IllegalArgumentException("URI string and source path must not be null or empty."); + } + + String[] uriParts = uriStr.trim().split("/"); + + if (uriParts.length < 2) { + throw new IllegalArgumentException("URI must contain both library name and file name."); + } + + // Use the src path to create a base path + Path rootPath = Paths.get(src).toAbsolutePath(); + + // Traverse upwards until we reach the "src/" directory + while (!rootPath.endsWith("src")) { + rootPath = rootPath.getParent(); + if (rootPath == null) { + throw new IllegalArgumentException("The 'src' directory was not found in the given path."); + } + } + + Path finalPath = + rootPath + .resolveSibling("target/lfc_include/") + .resolve(uriParts[0].trim()) // library name + .resolve("src/lib") + .resolve(uriParts[1].trim()); // file name + + return finalPath.toString(); + } +} diff --git a/test/Python/src/FederatedImportLibrary.lf b/test/Python/src/FederatedImportLibrary.lf deleted file mode 100644 index 17d500aa93..0000000000 --- a/test/Python/src/FederatedImportLibrary.lf +++ /dev/null @@ -1,20 +0,0 @@ -# Test the new import statement, with the import path enclosed in angle brackets, in federated LF programs -target Python { - timeout: 2 sec -} - -import Count from - -reactor Printer { - input i - - reaction(i) {= - print(f"Count: {i.value}") - =} -} - -federated reactor { - c = new Count() - p = new Printer() - c.out -> p.i -} diff --git a/test/Python/src/ImportLibrary.lf b/test/Python/src/ImportLibrary.lf deleted file mode 100644 index 962a616a6b..0000000000 --- a/test/Python/src/ImportLibrary.lf +++ /dev/null @@ -1,20 +0,0 @@ -# Test the new import statement with the import path enclosed in angle brackets -target Python { - timeout: 2 sec -} - -import Count from - -reactor Printer { - input i - - reaction(i) {= - print(f"Count: {i.value}") - =} -} - -main reactor { - c = new Count() - p = new Printer() - c.out -> p.i -} diff --git a/test/Python/src/lingo_imports/FederatedTestImportPackages.lf b/test/Python/src/lingo_imports/FederatedTestImportPackages.lf new file mode 100644 index 0000000000..6c642bae6f --- /dev/null +++ b/test/Python/src/lingo_imports/FederatedTestImportPackages.lf @@ -0,0 +1,20 @@ +# Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets +target Python { + timeout: 2 sec +} + +import Count from + +reactor Actuator { + input results + + reaction(results) {= + print(f"Count: {results.value}") + =} +} + +federated reactor { + count = new Count() + act = new Actuator() + count.out -> act.results +} diff --git a/test/Python/src/lingo_imports/TestImportPackages.lf b/test/Python/src/lingo_imports/TestImportPackages.lf new file mode 100644 index 0000000000..fc0915f160 --- /dev/null +++ b/test/Python/src/lingo_imports/TestImportPackages.lf @@ -0,0 +1,20 @@ +# Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets +target Python { + timeout: 2 sec +} + +import Count from + +reactor Actuator { + input results + + reaction(results) {= + print(f"Count: {results.value}") + =} +} + +main reactor { + count = new Count() + act = new Actuator() + count.out -> act.results +} diff --git a/test/Python/target/lfc_include/library-test/src/lib/Import.lf b/test/Python/target/lfc_include/library-test/src/lib/Import.lf new file mode 100644 index 0000000000..97ca1fb73f --- /dev/null +++ b/test/Python/target/lfc_include/library-test/src/lib/Import.lf @@ -0,0 +1,12 @@ +target Python + +reactor Count(offset=0, period = 1 sec) { + state count = 1 + output out + timer t(offset, period) + + reaction(t) -> out {= + out.set(self.count) + self.count += 1 + =} +} \ No newline at end of file From a32c7ed28ba9c3e7cc9373125c3aa224f82cfa01 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sun, 29 Sep 2024 21:11:20 -0700 Subject: [PATCH 050/136] Enhance path handling in ImportUtil.java and add new test --- .../main/java/org/lflang/util/ImportUtil.java | 62 +++++++++++-------- test/Python/src/LingoFederatedImport.lf | 21 +++++++ .../FederatedTestImportPackages.lf | 1 + 3 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 test/Python/src/LingoFederatedImport.lf diff --git a/core/src/main/java/org/lflang/util/ImportUtil.java b/core/src/main/java/org/lflang/util/ImportUtil.java index ef52e39e5f..2fdaf5e4f3 100644 --- a/core/src/main/java/org/lflang/util/ImportUtil.java +++ b/core/src/main/java/org/lflang/util/ImportUtil.java @@ -2,7 +2,6 @@ import java.nio.file.Path; import java.nio.file.Paths; -import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; /** @@ -15,7 +14,7 @@ public class ImportUtil { /** * Builds a package URI based on the provided URI string and resource. It traverses upwards from - * the current resource URI until it finds the "src/" directory, then constructs the final URI + * the current resource URI until it finds the "src" directory, then constructs the final URI * pointing to the library file within the "target/lfc_include" directory. * * @param uriStr A string representing the URI of the file. It must contain both the library name @@ -26,30 +25,37 @@ public class ImportUtil { * names. */ public static String buildPackageURI(String uriStr, Resource resource) { - URI currentURI = URI.createURI("."); - URI rootURI = currentURI.resolve(resource.getURI()); - StringBuilder pathBuilder = new StringBuilder(); + Path rootPath = Paths.get(resource.getURI().toString()).toAbsolutePath(); - String[] uriParts = uriStr.split("/"); + Path uriPath = Paths.get(uriStr.trim()); - if (uriParts.length < 2) { + if (uriPath.getNameCount() < 2) { throw new IllegalArgumentException("URI must contain both library name and file name."); } + // Initialize the path as the current directory + Path finalPath = Paths.get(""); + // Traverse upwards until we reach the "src/" directory - while (!rootURI.toString().endsWith("src/")) { - currentURI = URI.createURI(".."); - rootURI = currentURI.resolve(resource.getURI()); - pathBuilder.append("../"); + while (!rootPath.endsWith("src")) { + rootPath = rootPath.getParent(); + if (rootPath == null) { + throw new IllegalArgumentException("The 'src' directory was not found in the given path."); + } + finalPath = finalPath.resolve(".."); } - pathBuilder - .append("../target/lfc_include/") - .append(uriParts[0]) - .append("/src/lib/") - .append(uriParts[1]); + // Build the final path + finalPath = + finalPath + .resolve("target") + .resolve("lfc_include") + .resolve(uriPath.getName(0)) + .resolve("src") + .resolve("lib") + .resolve(uriPath.getName(1)); - return pathBuilder.toString(); + return finalPath.toString(); } /** @@ -60,24 +66,24 @@ public static String buildPackageURI(String uriStr, Resource resource) { * * @param uriStr A string representing the URI of the file. It must contain both the library name * and file name, separated by a '/'. - * @param src The source path from which the URI resolution should start. + * @param root The root path from which the URI resolution should start. * @return The constructed package URI as a string. * @throws IllegalArgumentException if the URI string or source path is null, empty, or does not * contain both the library name and file name. */ - public static String buildPackageURIfromSrc(String uriStr, String src) { - if (uriStr == null || src == null || uriStr.trim().isEmpty() || src.trim().isEmpty()) { + public static String buildPackageURIfromSrc(String uriStr, String root) { + if (uriStr == null || root == null || uriStr.trim().isEmpty() || root.trim().isEmpty()) { throw new IllegalArgumentException("URI string and source path must not be null or empty."); } - String[] uriParts = uriStr.trim().split("/"); + Path uriPath = Paths.get(uriStr.trim()); - if (uriParts.length < 2) { + if (uriPath.getNameCount() < 2) { throw new IllegalArgumentException("URI must contain both library name and file name."); } // Use the src path to create a base path - Path rootPath = Paths.get(src).toAbsolutePath(); + Path rootPath = Paths.get(root).toAbsolutePath(); // Traverse upwards until we reach the "src/" directory while (!rootPath.endsWith("src")) { @@ -89,10 +95,12 @@ public static String buildPackageURIfromSrc(String uriStr, String src) { Path finalPath = rootPath - .resolveSibling("target/lfc_include/") - .resolve(uriParts[0].trim()) // library name - .resolve("src/lib") - .resolve(uriParts[1].trim()); // file name + .resolveSibling("target") + .resolve("lfc_include") + .resolve(uriPath.getName(0)) // library name + .resolve("src") + .resolve("lib") + .resolve(uriPath.getName(1)); // file name return finalPath.toString(); } diff --git a/test/Python/src/LingoFederatedImport.lf b/test/Python/src/LingoFederatedImport.lf new file mode 100644 index 0000000000..5b3a4fadd6 --- /dev/null +++ b/test/Python/src/LingoFederatedImport.lf @@ -0,0 +1,21 @@ +# Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets +# Version 1: The LF file is located in "src". +target Python { + timeout: 2 sec +} + +import Count from + +reactor Actuator { + input results + + reaction(results) {= + print(f"Count: {results.value}") + =} +} + +federated reactor { + count = new Count() + act = new Actuator() + count.out -> act.results +} diff --git a/test/Python/src/lingo_imports/FederatedTestImportPackages.lf b/test/Python/src/lingo_imports/FederatedTestImportPackages.lf index 6c642bae6f..4081aa29ba 100644 --- a/test/Python/src/lingo_imports/FederatedTestImportPackages.lf +++ b/test/Python/src/lingo_imports/FederatedTestImportPackages.lf @@ -1,4 +1,5 @@ # Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets +# Version 2: The LF file is now located in a subdirectory under "src". target Python { timeout: 2 sec } From d5bdd9ae0cfdc5db57f6531846ce178c841a0e9a Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sun, 29 Sep 2024 22:22:58 -0700 Subject: [PATCH 051/136] Change ImportUtil.buildPackageURIfromSrc to return a Path object instead of a String --- .../java/org/lflang/federated/generator/FedImportEmitter.java | 3 ++- core/src/main/java/org/lflang/util/ImportUtil.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 8ffe120af1..883bc8d327 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -1,6 +1,7 @@ package org.lflang.federated.generator; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; @@ -37,7 +38,7 @@ String generateImports(FederateInstance federate, FederationFileConfig fileConfi .srcPath .resolve( i.getImportURI() != null - ? i.getImportURI() + ? Paths.get(i.getImportURI()) : ImportUtil.buildPackageURIfromSrc( i.getImportPackage(), fileConfig.srcPath.toString())) .toAbsolutePath(); diff --git a/core/src/main/java/org/lflang/util/ImportUtil.java b/core/src/main/java/org/lflang/util/ImportUtil.java index 2fdaf5e4f3..60cf383be3 100644 --- a/core/src/main/java/org/lflang/util/ImportUtil.java +++ b/core/src/main/java/org/lflang/util/ImportUtil.java @@ -71,7 +71,7 @@ public static String buildPackageURI(String uriStr, Resource resource) { * @throws IllegalArgumentException if the URI string or source path is null, empty, or does not * contain both the library name and file name. */ - public static String buildPackageURIfromSrc(String uriStr, String root) { + public static Path buildPackageURIfromSrc(String uriStr, String root) { if (uriStr == null || root == null || uriStr.trim().isEmpty() || root.trim().isEmpty()) { throw new IllegalArgumentException("URI string and source path must not be null or empty."); } @@ -102,6 +102,6 @@ public static String buildPackageURIfromSrc(String uriStr, String root) { .resolve("lib") .resolve(uriPath.getName(1)); // file name - return finalPath.toString(); + return finalPath; } } From b4278678421f6a36b263c9d232d8f0cfb514d98d Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 30 Sep 2024 20:22:48 -0700 Subject: [PATCH 052/136] Fix disconnected port handling --- .../java/org/lflang/generator/c/CTriggerObjectsGenerator.java | 3 +++ core/src/main/resources/lib/c/reactor-c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CTriggerObjectsGenerator.java b/core/src/main/java/org/lflang/generator/c/CTriggerObjectsGenerator.java index cf1587ae85..ebef8e5933 100644 --- a/core/src/main/java/org/lflang/generator/c/CTriggerObjectsGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CTriggerObjectsGenerator.java @@ -911,6 +911,9 @@ private static String deferredReactionOutputs( // If the port is a multiport, then we need to create an entry for each // individual channel. + // If this port does not have any destinations, do not generate code for it. + if (effect.eventualDestinations().isEmpty()) continue; + // If the port is an input of a contained reactor, then, if that // contained reactor is a bank, we will have to iterate over bank // members. diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 165f3fe107..815696c5d5 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 165f3fe1077eb98f3a888a70d61a710bfac59778 +Subproject commit 815696c5d53775755e55dc8da4c6fb99f218efe1 From d1bcd7d1af9eb1aaba545d1f7b6c9cc8aa600e8f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 30 Sep 2024 20:24:42 -0700 Subject: [PATCH 053/136] Added test --- test/C/src/TriggerIssue.lf | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test/C/src/TriggerIssue.lf diff --git a/test/C/src/TriggerIssue.lf b/test/C/src/TriggerIssue.lf new file mode 100644 index 0000000000..c3f5b1601b --- /dev/null +++ b/test/C/src/TriggerIssue.lf @@ -0,0 +1,42 @@ +/** + * Destination cannot react to y. Only if x is also a trigger (uncomment + * reaction) it will work. + */ + target C { + logging: debug +} + +reactor Source { + output x: bool + output y: bool + + reaction(startup) -> x, y {= + lf_print("S"); + lf_set(y, true); + =} +} + +reactor Destination { + input y: bool + + state gotY: bool = false + + reaction(y) {= + lf_print("Y"); + self->gotY = true; + =} + + reaction(shutdown) {= + if (!self->gotY) { + lf_print_error_and_exit("No reaction to Y!"); + } + =} +} + +main reactor { + ui = new Source() + dlc = new Destination() + + // ui.x -> dlc.x + ui.y -> dlc.y +} From 3d2c80389163114e49ee7d6c0e102b871c3080ce Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 30 Sep 2024 21:03:04 -0700 Subject: [PATCH 054/136] Format and remove commented out line --- test/C/src/TriggerIssue.lf | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/test/C/src/TriggerIssue.lf b/test/C/src/TriggerIssue.lf index c3f5b1601b..9101349117 100644 --- a/test/C/src/TriggerIssue.lf +++ b/test/C/src/TriggerIssue.lf @@ -1,8 +1,5 @@ -/** - * Destination cannot react to y. Only if x is also a trigger (uncomment - * reaction) it will work. - */ - target C { +/** Destination cannot react to y. Only if x is also a trigger (uncomment reaction) it will work. */ +target C { logging: debug } @@ -11,8 +8,8 @@ reactor Source { output y: bool reaction(startup) -> x, y {= - lf_print("S"); - lf_set(y, true); + lf_print("S"); + lf_set(y, true); =} } @@ -22,14 +19,14 @@ reactor Destination { state gotY: bool = false reaction(y) {= - lf_print("Y"); - self->gotY = true; + lf_print("Y"); + self->gotY = true; =} reaction(shutdown) {= - if (!self->gotY) { - lf_print_error_and_exit("No reaction to Y!"); - } + if (!self->gotY) { + lf_print_error_and_exit("No reaction to Y!"); + } =} } @@ -37,6 +34,4 @@ main reactor { ui = new Source() dlc = new Destination() - // ui.x -> dlc.x ui.y -> dlc.y -} From 5dba6e557e72f845910c82c08d3af4d27375516b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 30 Sep 2024 21:15:54 -0700 Subject: [PATCH 055/136] Typo --- test/C/src/TriggerIssue.lf | 1 + 1 file changed, 1 insertion(+) diff --git a/test/C/src/TriggerIssue.lf b/test/C/src/TriggerIssue.lf index 9101349117..d16506dc2f 100644 --- a/test/C/src/TriggerIssue.lf +++ b/test/C/src/TriggerIssue.lf @@ -35,3 +35,4 @@ main reactor { dlc = new Destination() ui.y -> dlc.y +} From d6d6cd6deee29db19ec08812f37cd67628bb5c6f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Tue, 1 Oct 2024 08:11:24 -0700 Subject: [PATCH 056/136] Fixed comment --- test/C/src/TriggerIssue.lf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/C/src/TriggerIssue.lf b/test/C/src/TriggerIssue.lf index d16506dc2f..b8ad6462c1 100644 --- a/test/C/src/TriggerIssue.lf +++ b/test/C/src/TriggerIssue.lf @@ -1,4 +1,4 @@ -/** Destination cannot react to y. Only if x is also a trigger (uncomment reaction) it will work. */ +/** Testing that unconnected port does not block triggering. */ target C { logging: debug } From a76d1f43e65f675df742b0cb1794e8de1a7fa2d9 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Tue, 1 Oct 2024 08:35:41 -0700 Subject: [PATCH 057/136] Additional test --- test/C/src/TriggerIssue2.lf | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/C/src/TriggerIssue2.lf diff --git a/test/C/src/TriggerIssue2.lf b/test/C/src/TriggerIssue2.lf new file mode 100644 index 0000000000..d2441b14f0 --- /dev/null +++ b/test/C/src/TriggerIssue2.lf @@ -0,0 +1,41 @@ +/** Test that untriggered reactions are not triggered. */ +target C +reactor OnlySuccess { + input start:bool + output success:bool + output failure:bool + + reaction (start) -> success, failure {= + lf_print("Create Success"); + lf_set(success, true); + =} +} +reactor ForwardFailure { + input in:bool + output out:bool + reaction (in) -> out {= + lf_print("Forward Failure"); + lf_set(out, true); + =} +} +reactor Sequence { + input start:bool + output success:bool + output failure:bool + s = new OnlySuccess(); + f = new ForwardFailure(); + start -> s.start + s.success -> success + s.failure -> f.in + f.out -> failure +} +main reactor { + s = new Sequence() + reaction(startup) -> s.start {= + lf_print("Start"); + lf_set(s.start, true); + =} + reaction(s.failure) {= + lf_print_error_and_exit("Failure"); + =} +} From 7a0a20bba890b54c20c0707ef5f6253849addcfd Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Tue, 1 Oct 2024 08:50:00 -0700 Subject: [PATCH 058/136] Spotless --- test/C/src/TriggerIssue2.lf | 69 ++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/test/C/src/TriggerIssue2.lf b/test/C/src/TriggerIssue2.lf index d2441b14f0..2803b313bb 100644 --- a/test/C/src/TriggerIssue2.lf +++ b/test/C/src/TriggerIssue2.lf @@ -1,41 +1,48 @@ /** Test that untriggered reactions are not triggered. */ target C + reactor OnlySuccess { - input start:bool - output success:bool - output failure:bool - - reaction (start) -> success, failure {= - lf_print("Create Success"); - lf_set(success, true); - =} + input start: bool + output success: bool + output failure: bool + + reaction(start) -> success, failure {= + lf_print("Create Success"); + lf_set(success, true); + =} } + reactor ForwardFailure { - input in:bool - output out:bool - reaction (in) -> out {= - lf_print("Forward Failure"); - lf_set(out, true); - =} + input in: bool + output out: bool + + reaction(in) -> out {= + lf_print("Forward Failure"); + lf_set(out, true); + =} } + reactor Sequence { - input start:bool - output success:bool - output failure:bool - s = new OnlySuccess(); - f = new ForwardFailure(); - start -> s.start - s.success -> success - s.failure -> f.in - f.out -> failure + input start: bool + output success: bool + output failure: bool + s = new OnlySuccess() + f = new ForwardFailure() + start -> s.start + s.success -> success + s.failure -> f.in + f.out -> failure } + main reactor { - s = new Sequence() - reaction(startup) -> s.start {= - lf_print("Start"); - lf_set(s.start, true); - =} - reaction(s.failure) {= - lf_print_error_and_exit("Failure"); - =} + s = new Sequence() + + reaction(startup) -> s.start {= + lf_print("Start"); + lf_set(s.start, true); + =} + + reaction(s.failure) {= + lf_print_error_and_exit("Failure"); + =} } From 6427abb106c4a1a92cc791f3c5b574bfc5c77a09 Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Tue, 1 Oct 2024 16:37:03 -0700 Subject: [PATCH 059/136] Changed path in ImportUtil from 'target/lfc_include' to 'build/lfc_include' --- .gitignore | 3 +++ core/src/main/java/org/lflang/util/ImportUtil.java | 8 ++++---- .../lfc_include/library-test/src/lib/Import.lf | 0 3 files changed, 7 insertions(+), 4 deletions(-) rename test/Python/{target => build}/lfc_include/library-test/src/lib/Import.lf (100%) diff --git a/.gitignore b/.gitignore index da8902f971..193c7b8a77 100644 --- a/.gitignore +++ b/.gitignore @@ -170,3 +170,6 @@ gradle-app.setting *.jar core/model/ +# Exclude all build directories except test/Python/build for testing purposes +!test/Python/build/ + diff --git a/core/src/main/java/org/lflang/util/ImportUtil.java b/core/src/main/java/org/lflang/util/ImportUtil.java index 60cf383be3..b7de0a16d4 100644 --- a/core/src/main/java/org/lflang/util/ImportUtil.java +++ b/core/src/main/java/org/lflang/util/ImportUtil.java @@ -7,7 +7,7 @@ /** * Utility class for handling package-related URIs in the context of LF (Lingua Franca) libraries. * This class provides methods to build URIs for accessing library files based on their location in - * a project structure, specifically targeting the "target/lfc_include" directory for library + * a project structure, specifically targeting the "build/lfc_include" directory for library * inclusion. */ public class ImportUtil { @@ -15,7 +15,7 @@ public class ImportUtil { /** * Builds a package URI based on the provided URI string and resource. It traverses upwards from * the current resource URI until it finds the "src" directory, then constructs the final URI - * pointing to the library file within the "target/lfc_include" directory. + * pointing to the library file within the "build/lfc_include" directory. * * @param uriStr A string representing the URI of the file. It must contain both the library name * and file name, separated by a '/'. @@ -48,7 +48,7 @@ public static String buildPackageURI(String uriStr, Resource resource) { // Build the final path finalPath = finalPath - .resolve("target") + .resolve("build") .resolve("lfc_include") .resolve(uriPath.getName(0)) .resolve("src") @@ -95,7 +95,7 @@ public static Path buildPackageURIfromSrc(String uriStr, String root) { Path finalPath = rootPath - .resolveSibling("target") + .resolveSibling("build") .resolve("lfc_include") .resolve(uriPath.getName(0)) // library name .resolve("src") diff --git a/test/Python/target/lfc_include/library-test/src/lib/Import.lf b/test/Python/build/lfc_include/library-test/src/lib/Import.lf similarity index 100% rename from test/Python/target/lfc_include/library-test/src/lib/Import.lf rename to test/Python/build/lfc_include/library-test/src/lib/Import.lf From 2d9a7c28c12484953fcf7608bf0e36f82f1479f6 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 3 Oct 2024 04:48:52 -0700 Subject: [PATCH 060/136] Fixed #2117 and added tests --- .../generator/c/CReactionGenerator.java | 12 ++--- core/src/main/resources/lib/c/reactor-c | 2 +- test/C/src/Mutable.lf | 36 +++++++++++++++ test/C/src/token/MutableToken.lf | 46 +++++++++++++++++++ 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 test/C/src/Mutable.lf create mode 100644 test/C/src/token/MutableToken.lf diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index 151d2a47fb..41aeba5895 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -694,11 +694,11 @@ private static String generateInputVariablesInReaction( structType + " _lf_tmp_" + inputName - + "[" + + "[self->" + CUtil.multiportWidthExpression(input) + "];", - structType + "* " + inputName + "[" + CUtil.multiportWidthExpression(input) + "];", - "for (int i = 0; i < " + CUtil.multiportWidthExpression(input) + "; i++) {", + structType + "* " + inputName + "[self->" + CUtil.multiportWidthExpression(input) + "];", + "for (int i = 0; i < self->" + CUtil.multiportWidthExpression(input) + "; i++) {", " " + inputName + "[i] = &_lf_tmp_" + inputName + "[i];", " _lf_tmp_" + inputName + "[i] = *(self->_lf_" + inputName + "[i]);", " // If necessary, copy the tokens.", @@ -732,11 +732,11 @@ private static String generateInputVariablesInReaction( structType + " _lf_tmp_" + inputName - + "[" + + "[self->" + CUtil.multiportWidthExpression(input) + "];", - structType + "* " + inputName + "[" + CUtil.multiportWidthExpression(input) + "];", - "for (int i = 0; i < " + CUtil.multiportWidthExpression(input) + "; i++) {", + structType + "* " + inputName + "[self->" + CUtil.multiportWidthExpression(input) + "];", + "for (int i = 0; i < self->" + CUtil.multiportWidthExpression(input) + "; i++) {", " " + inputName + "[i] = &_lf_tmp_" + inputName + "[i];", " // Copy the struct, which includes the value.", " _lf_tmp_" + inputName + "[i] = *(self->_lf_" + inputName + "[i]);", diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 815696c5d5..bea933ff67 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 815696c5d53775755e55dc8da4c6fb99f218efe1 +Subproject commit bea933ff67fa976013fcbd73bfaa1e88f6d846a9 diff --git a/test/C/src/Mutable.lf b/test/C/src/Mutable.lf new file mode 100644 index 0000000000..2f03613cea --- /dev/null +++ b/test/C/src/Mutable.lf @@ -0,0 +1,36 @@ +target C; +reactor S(width:int = 4) { + output[width] out:int + reaction(startup) -> out {= + for(int i = 0; i < self->width; i++) { + lf_set(out[i], 0); + } + =} +} +reactor R(width:int=4) { + mutable input[width] in: int + output[width] out: int + reaction(in) -> out {= + for(int i = 0; i < self->width; i++) { + in[i]->value = (i + 1) * 2; + lf_set(out[i], in[i]->value); + } + =} +} +main reactor { + s = new S(width = 2) + r = new R(width = 2) + s.out -> r.in + reaction(r.out) {= + lf_print("Received from R %d, %d", r.out[0]->value, r.out[1]->value); + if (r.out[0]->value != 2 || r.out[1]->value != 4) { + lf_print_error_and_exit("Expected 2 and 4."); + } + =} + reaction(s.out) {= + lf_print("Received from S %d, %d", s.out[0]->value, s.out[1]->value); + if (s.out[0]->value != 0 || s.out[1]->value != 0) { + lf_print_error_and_exit("Expected zeros."); + } + =} +} diff --git a/test/C/src/token/MutableToken.lf b/test/C/src/token/MutableToken.lf new file mode 100644 index 0000000000..86b64bc0a2 --- /dev/null +++ b/test/C/src/token/MutableToken.lf @@ -0,0 +1,46 @@ +target C { + timeout: 0s, + files: ["include/array.h"] +} + +import TokenSource from "lib/Token.lf" + +preamble {= + #include "array.h" +=} + +reactor R(width:int=4) { + mutable input[width] in: int_array_t* + output[width] out: int_array_t* + reaction(in) -> out {= + for(int i = 0; i < self->width; i++) { + for (int j = 0; j < in[i]->value->length; j++) { + in[i]->value->data[j] = in[i]->value->data[j] * 2; + } + lf_set_token(out[i], in[i]->token); + } + =} +} +main reactor { + s = new[2] TokenSource() + r = new R(width = 2) + s.out -> r.in + reaction(r.out) {= + lf_print("Received from R [%d, %d, %d], [%d, %d, %d]", + r.out[0]->value->data[0], r.out[0]->value->data[1], r.out[0]->value->data[2], + r.out[1]->value->data[0], r.out[1]->value->data[1], r.out[1]->value->data[2]); + if (r.out[0]->value->data[0] != 0 || r.out[0]->value->data[1] != 2 || r.out[0]->value->data[2] != 4 + || r.out[1]->value->data[0] != 0 || r.out[1]->value->data[1] != 2 || r.out[1]->value->data[2] != 4) { + lf_print_error_and_exit("Expected [0, 2, 4]."); + } + =} + reaction(s.out) {= + lf_print("Received from S [%d, %d, %d], [%d, %d, %d]", + s[0].out->value->data[0], s[0].out->value->data[1], s[0].out->value->data[2], + s[1].out->value->data[0], s[1].out->value->data[1], s[1].out->value->data[2]); + if (s[0].out->value->data[0] != 0 || s[0].out->value->data[1] != 1 || s[0].out->value->data[2] != 2 + || s[1].out->value->data[0] != 0 || s[1].out->value->data[1] != 1 || s[1].out->value->data[2] != 2) { + lf_print_error_and_exit("Expected [0, 2, 4]."); + } + =} +} From cae55a438c283c4afc2b25703f033ebd19411161 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 3 Oct 2024 04:52:12 -0700 Subject: [PATCH 061/136] Format --- test/C/src/Mutable.lf | 19 +++++++++++++------ test/C/src/token/MutableToken.lf | 10 +++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/test/C/src/Mutable.lf b/test/C/src/Mutable.lf index 2f03613cea..575473986f 100644 --- a/test/C/src/Mutable.lf +++ b/test/C/src/Mutable.lf @@ -1,15 +1,19 @@ -target C; -reactor S(width:int = 4) { - output[width] out:int +target C + +reactor S(width: int = 4) { + output[width] out: int + reaction(startup) -> out {= for(int i = 0; i < self->width; i++) { lf_set(out[i], 0); } =} } -reactor R(width:int=4) { + +reactor R(width: int = 4) { mutable input[width] in: int output[width] out: int + reaction(in) -> out {= for(int i = 0; i < self->width; i++) { in[i]->value = (i + 1) * 2; @@ -17,16 +21,19 @@ reactor R(width:int=4) { } =} } + main reactor { - s = new S(width = 2) - r = new R(width = 2) + s = new S(width=2) + r = new R(width=2) s.out -> r.in + reaction(r.out) {= lf_print("Received from R %d, %d", r.out[0]->value, r.out[1]->value); if (r.out[0]->value != 2 || r.out[1]->value != 4) { lf_print_error_and_exit("Expected 2 and 4."); } =} + reaction(s.out) {= lf_print("Received from S %d, %d", s.out[0]->value, s.out[1]->value); if (s.out[0]->value != 0 || s.out[1]->value != 0) { diff --git a/test/C/src/token/MutableToken.lf b/test/C/src/token/MutableToken.lf index 86b64bc0a2..724b8a6579 100644 --- a/test/C/src/token/MutableToken.lf +++ b/test/C/src/token/MutableToken.lf @@ -1,5 +1,5 @@ target C { - timeout: 0s, + timeout: 0 s, files: ["include/array.h"] } @@ -9,9 +9,10 @@ preamble {= #include "array.h" =} -reactor R(width:int=4) { +reactor R(width: int = 4) { mutable input[width] in: int_array_t* output[width] out: int_array_t* + reaction(in) -> out {= for(int i = 0; i < self->width; i++) { for (int j = 0; j < in[i]->value->length; j++) { @@ -21,10 +22,12 @@ reactor R(width:int=4) { } =} } + main reactor { s = new[2] TokenSource() - r = new R(width = 2) + r = new R(width=2) s.out -> r.in + reaction(r.out) {= lf_print("Received from R [%d, %d, %d], [%d, %d, %d]", r.out[0]->value->data[0], r.out[0]->value->data[1], r.out[0]->value->data[2], @@ -34,6 +37,7 @@ main reactor { lf_print_error_and_exit("Expected [0, 2, 4]."); } =} + reaction(s.out) {= lf_print("Received from S [%d, %d, %d], [%d, %d, %d]", s[0].out->value->data[0], s[0].out->value->data[1], s[0].out->value->data[2], From 58d965f40714939c2a0726f6fda0f53710fa9ffd Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 3 Oct 2024 06:11:39 -0700 Subject: [PATCH 062/136] Use self-> modifier only for variables --- .../org/lflang/generator/c/CReactionGenerator.java | 12 ++++++------ core/src/main/java/org/lflang/generator/c/CUtil.java | 2 +- core/src/main/resources/lib/c/reactor-c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index 41aeba5895..151d2a47fb 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -694,11 +694,11 @@ private static String generateInputVariablesInReaction( structType + " _lf_tmp_" + inputName - + "[self->" + + "[" + CUtil.multiportWidthExpression(input) + "];", - structType + "* " + inputName + "[self->" + CUtil.multiportWidthExpression(input) + "];", - "for (int i = 0; i < self->" + CUtil.multiportWidthExpression(input) + "; i++) {", + structType + "* " + inputName + "[" + CUtil.multiportWidthExpression(input) + "];", + "for (int i = 0; i < " + CUtil.multiportWidthExpression(input) + "; i++) {", " " + inputName + "[i] = &_lf_tmp_" + inputName + "[i];", " _lf_tmp_" + inputName + "[i] = *(self->_lf_" + inputName + "[i]);", " // If necessary, copy the tokens.", @@ -732,11 +732,11 @@ private static String generateInputVariablesInReaction( structType + " _lf_tmp_" + inputName - + "[self->" + + "[" + CUtil.multiportWidthExpression(input) + "];", - structType + "* " + inputName + "[self->" + CUtil.multiportWidthExpression(input) + "];", - "for (int i = 0; i < self->" + CUtil.multiportWidthExpression(input) + "; i++) {", + structType + "* " + inputName + "[" + CUtil.multiportWidthExpression(input) + "];", + "for (int i = 0; i < " + CUtil.multiportWidthExpression(input) + "; i++) {", " " + inputName + "[i] = &_lf_tmp_" + inputName + "[i];", " // Copy the struct, which includes the value.", " _lf_tmp_" + inputName + "[i] = *(self->_lf_" + inputName + "[i]);", diff --git a/core/src/main/java/org/lflang/generator/c/CUtil.java b/core/src/main/java/org/lflang/generator/c/CUtil.java index 64e63bfe95..dae1425342 100644 --- a/core/src/main/java/org/lflang/generator/c/CUtil.java +++ b/core/src/main/java/org/lflang/generator/c/CUtil.java @@ -755,7 +755,7 @@ private static List multiportWidthTerms(Variable variable) { if (!((Port) variable).getWidthSpec().isOfVariableLength()) { for (WidthTerm term : ((Port) variable).getWidthSpec().getTerms()) { if (term.getParameter() != null) { - result.add(getTargetReference(term.getParameter())); + result.add("self->" + getTargetReference(term.getParameter())); } else { result.add(String.valueOf(term.getWidth())); } diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index bea933ff67..7208c9f02e 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit bea933ff67fa976013fcbd73bfaa1e88f6d846a9 +Subproject commit 7208c9f02e991f85dd85cef0c4cb576dcf1deebb From b47c1790bda37e4c42d298fafabeeb6951c0ce05 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 3 Oct 2024 06:13:57 -0700 Subject: [PATCH 063/136] Align reactor-c --- core/src/main/resources/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 7208c9f02e..693c5f5bdb 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 7208c9f02e991f85dd85cef0c4cb576dcf1deebb +Subproject commit 693c5f5bdbc6918cebc619c3ae46a22af719b741 From d51f98f252aeed04918aab9060a8578d7d23d028 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 3 Oct 2024 10:04:07 -0700 Subject: [PATCH 064/136] Remove EnclaveRequestShutdown --- test/C/src/enclave/EnclaveRequestStop.lf | 29 ------------------------ 1 file changed, 29 deletions(-) delete mode 100644 test/C/src/enclave/EnclaveRequestStop.lf diff --git a/test/C/src/enclave/EnclaveRequestStop.lf b/test/C/src/enclave/EnclaveRequestStop.lf deleted file mode 100644 index aea05a874d..0000000000 --- a/test/C/src/enclave/EnclaveRequestStop.lf +++ /dev/null @@ -1,29 +0,0 @@ -/** Test that enclaves all stop at the time requested by the first enclave to request a stop. */ -target C { - timeout: 1 sec -} - -reactor Stop(stop_time: time = 5 s) { - preamble {= - #include "platform.h" // Defines PRINTF_TIME - =} - timer t(stop_time) - - reaction(t) {= - lf_request_stop(); - =} - - reaction(shutdown) {= - lf_print("Stopped at tag (" PRINTF_TIME ", %d)", lf_time_logical_elapsed(), lf_tag().microstep); - if (lf_time_logical_elapsed() != 50000000LL || lf_tag().microstep != 1) { - lf_print_error_and_exit("Expected stop tag to be (50ms, 1)."); - } - =} -} - -main reactor { - @enclave - s1 = new Stop() - @enclave - s2 = new Stop(stop_time = 50 ms) -} From eaac986f98251355fea600efb68457192ea22fda Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 3 Oct 2024 11:50:38 -0700 Subject: [PATCH 065/136] Fixed test so that stop time is not earlier than request_stop time --- test/C/src/enclave/EnclaveRequestStop.lf | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/C/src/enclave/EnclaveRequestStop.lf diff --git a/test/C/src/enclave/EnclaveRequestStop.lf b/test/C/src/enclave/EnclaveRequestStop.lf new file mode 100644 index 0000000000..91df3b1a60 --- /dev/null +++ b/test/C/src/enclave/EnclaveRequestStop.lf @@ -0,0 +1,29 @@ +/** Test that enclaves all stop at the time requested by the first enclave to request a stop. */ +target C { + timeout: 10 sec +} + +reactor Stop(stop_time: time = 5 s) { + preamble {= + #include "platform.h" // Defines PRINTF_TIME + =} + timer t(stop_time) + + reaction(t) {= + lf_request_stop(); + =} + + reaction(shutdown) {= + lf_print("Stopped at tag (" PRINTF_TIME ", %d)", lf_time_logical_elapsed(), lf_tag().microstep); + if (lf_time_logical_elapsed() != 50000000LL || lf_tag().microstep != 1) { + lf_print_error_and_exit("Expected stop tag to be (50ms, 1)."); + } + =} +} + +main reactor { + @enclave + s1 = new Stop() + @enclave + s2 = new Stop(stop_time = 50 ms) +} From c9649e30e8f804b797d151a642c00d45958bb2b5 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 4 Oct 2024 17:09:41 -0700 Subject: [PATCH 066/136] feat: forever time literal --- .../main/java/org/lflang/LinguaFranca.xtext | 6 ++++- .../main/java/org/lflang/ast/ASTUtils.java | 26 +++++++++++++++++++ .../org/lflang/generator/TargetTypes.java | 2 ++ test/Python/src/federated/Dataflow.lf | 10 +++---- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index ba45b3bd0c..11275cc82f 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -392,8 +392,12 @@ SignedInt: INT | NEGINT ; +Forever: + 'FOREVER' | 'forever' +; + Literal: - STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean + STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean | Forever ; Boolean: diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 4f4f843fd3..5f2d3dd526 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -944,6 +944,17 @@ public static boolean isZero(String literal) { return false; } + /** + * Report whether the given literal is forever or not. + * + * @param literal AST node to inspect. + * @return True if the given literal denotes the constant {@code FOREVER} or {@code forever}, false otherwise. + */ + public static boolean isForever(String literal) { + return literal != null && (literal.equals("FOREVER") || literal.equals("forever")); + } + + /** * Report whether the given expression is zero or not. * @@ -957,6 +968,19 @@ public static boolean isZero(Expression expr) { return false; } + /** + * Report whether the given expression is forever or not. + * + * @param expr AST node to inspect. + * @return True if the given value denotes the constant {@code FOREVER} or {@code forever}, false otherwise. + */ + public static boolean isForever(Expression expr) { + if (expr instanceof Literal) { + return isForever(((Literal) expr).getLiteral()); + } + return false; + } + /** * Report whether the given string literal is an integer number or not. * @@ -1137,6 +1161,8 @@ public static TimeValue getLiteralTimeValue(Expression expr) { return toTimeValue((Time) expr); } else if (expr instanceof Literal && isZero(((Literal) expr).getLiteral())) { return TimeValue.ZERO; + } else if (expr instanceof Literal && isForever(((Literal) expr).getLiteral())) { + return TimeValue.MAX_VALUE; } else { return null; } diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index 86bad63818..4291cdc45e 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -176,6 +176,8 @@ default String getTargetInitializer(Initializer init, Type type) { default String getTargetExpr(Expression expr, InferredType type) { if (ASTUtils.isZero(expr) && type != null && type.isTime) { return getTargetTimeExpr(TimeValue.ZERO); + } else if (ASTUtils.isForever(expr) && type != null && type.isTime) { + return getTargetTimeExpr(TimeValue.MAX_VALUE); } else if (expr instanceof ParameterReference) { return getTargetParamRef((ParameterReference) expr, type); } else if (expr instanceof Time) { diff --git a/test/Python/src/federated/Dataflow.lf b/test/Python/src/federated/Dataflow.lf index 4d33235af2..0daac98a6e 100644 --- a/test/Python/src/federated/Dataflow.lf +++ b/test/Python/src/federated/Dataflow.lf @@ -6,7 +6,7 @@ preamble {= import time =} -reactor Client(STP_offset = {= FOREVER =}) { +reactor Client(STP_offset = FOREVER) { input server_message output client_message @@ -24,13 +24,13 @@ reactor Client(STP_offset = {= FOREVER =}) { request_stop() # Need to unconditionally produce output or downstream could lock up waiting for it. client_message.set(val) - =} STP(10 s) {= + =} STP(FOREVER) {= print("Client STP Violated!") exit(1) =} } -reactor Server(STP_offset = {= FOREVER =}) { +reactor Server(STP_offset = FOREVER) { output server_message input client_message1 input client_message2 @@ -51,13 +51,13 @@ reactor Server(STP_offset = {= FOREVER =}) { request_stop() # Need to unconditionally produce output or downstream could lock up waiting for it. server_message.set(val) - =} STP(10 s) {= + =} STP(FOREVER) {= print("Server STP Violated!") exit(1) =} } -federated reactor(STP_offset = {= FOREVER =}) { +federated reactor(STP_offset = FOREVER) { client1 = new Client() client2 = new Client() server = new Server() From aea3135a2b1a59480f3729bccfe5b706773655f3 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 4 Oct 2024 17:13:07 -0700 Subject: [PATCH 067/136] change STP to STA and STAA --- core/src/main/java/org/lflang/ast/ASTUtils.java | 9 +++++---- test/Python/src/federated/Dataflow.lf | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 5f2d3dd526..a7e1c80595 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -948,13 +948,13 @@ public static boolean isZero(String literal) { * Report whether the given literal is forever or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code FOREVER} or {@code forever}, false otherwise. + * @return True if the given literal denotes the constant {@code FOREVER} or {@code forever}, + * false otherwise. */ public static boolean isForever(String literal) { - return literal != null && (literal.equals("FOREVER") || literal.equals("forever")); + return literal != null && (literal.equals("FOREVER") || literal.equals("forever")); } - /** * Report whether the given expression is zero or not. * @@ -972,7 +972,8 @@ public static boolean isZero(Expression expr) { * Report whether the given expression is forever or not. * * @param expr AST node to inspect. - * @return True if the given value denotes the constant {@code FOREVER} or {@code forever}, false otherwise. + * @return True if the given value denotes the constant {@code FOREVER} or {@code forever}, false + * otherwise. */ public static boolean isForever(Expression expr) { if (expr instanceof Literal) { diff --git a/test/Python/src/federated/Dataflow.lf b/test/Python/src/federated/Dataflow.lf index 0daac98a6e..892af49649 100644 --- a/test/Python/src/federated/Dataflow.lf +++ b/test/Python/src/federated/Dataflow.lf @@ -6,7 +6,7 @@ preamble {= import time =} -reactor Client(STP_offset = FOREVER) { +reactor Client(STA=FOREVER) { input server_message output client_message @@ -25,12 +25,12 @@ reactor Client(STP_offset = FOREVER) { # Need to unconditionally produce output or downstream could lock up waiting for it. client_message.set(val) =} STP(FOREVER) {= - print("Client STP Violated!") + print("Client STAA Violated!") exit(1) =} } -reactor Server(STP_offset = FOREVER) { +reactor Server(STA=FOREVER) { output server_message input client_message1 input client_message2 @@ -52,12 +52,12 @@ reactor Server(STP_offset = FOREVER) { # Need to unconditionally produce output or downstream could lock up waiting for it. server_message.set(val) =} STP(FOREVER) {= - print("Server STP Violated!") + print("Server STAA Violated!") exit(1) =} } -federated reactor(STP_offset = FOREVER) { +federated reactor(STA=FOREVER) { client1 = new Client() client2 = new Client() server = new Server() From af6f2b35d4aa2dbf78d92c44c0ea7719ba7b86f7 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 09:50:48 -0700 Subject: [PATCH 068/136] Start towards fixing multiports in modes --- .../org/lflang/generator/GeneratorBase.java | 18 +---- .../org/lflang/generator/c/CGenerator.java | 53 ++++++++++----- .../generator/python/PythonGenerator.java | 9 ++- core/src/main/resources/lib/c/reactor-c | 2 +- test/C/src/modal_models/ModalMultiport.lf | 67 +++++++++++++++++++ 5 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 test/C/src/modal_models/ModalMultiport.lf diff --git a/core/src/main/java/org/lflang/generator/GeneratorBase.java b/core/src/main/java/org/lflang/generator/GeneratorBase.java index 0713b863be..b3ef1a6491 100644 --- a/core/src/main/java/org/lflang/generator/GeneratorBase.java +++ b/core/src/main/java/org/lflang/generator/GeneratorBase.java @@ -53,13 +53,7 @@ import org.lflang.generator.docker.DockerComposeGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.graph.InstantiationGraph; -import org.lflang.lf.Attribute; -import org.lflang.lf.Connection; -import org.lflang.lf.Instantiation; -import org.lflang.lf.LfFactory; -import org.lflang.lf.Mode; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.FilesProperty; @@ -441,13 +435,7 @@ private void transformConflictingConnectionsInModalReactors(Set resour reaction.getEffects().add(destRef); var code = factory.createCode(); - var source = - (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") - + sourceRef.getVariable().getName(); - var dest = - (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") - + destRef.getVariable().getName(); - code.setBody(getConflictingConnectionsInModalReactorsBody(source, dest)); + code.setBody(getConflictingConnectionsInModalReactorsBody(sourceRef, destRef)); reaction.setCode(code); EcoreUtil.remove(connection); @@ -464,7 +452,7 @@ private void transformConflictingConnectionsInModalReactors(Set resour *

This method needs to be overridden in target specific code generators that support modal * reactors. */ - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { + protected String getConflictingConnectionsInModalReactorsBody(VarRef source, VarRef dest) { messageReporter .nowhere() .error( diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index f6ee943085..d9436371e4 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -70,18 +70,7 @@ import org.lflang.generator.docker.CDockerGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.generator.python.PythonGenerator; -import org.lflang.lf.Action; -import org.lflang.lf.ActionOrigin; -import org.lflang.lf.Input; -import org.lflang.lf.Instantiation; -import org.lflang.lf.Mode; -import org.lflang.lf.Port; -import org.lflang.lf.Preamble; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; -import org.lflang.lf.StateVar; -import org.lflang.lf.Variable; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.BuildCommandsProperty; @@ -659,12 +648,40 @@ public void checkModalReactorSupport(boolean __) { } @Override - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { - return String.join( - "\n", - "// Generated forwarding reaction for connections with the same destination", - "// but located in mutually exclusive modes.", - "lf_set(" + dest + ", " + source + "->value);"); + protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { + Instantiation sourceContainer = sourceRef.getContainer(); + Instantiation destContainer = destRef.getContainer(); + Port sourceAsPort = (Port) sourceRef.getVariable(); + Port destAsPort = (Port) destRef.getVariable(); + WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); + WidthSpec destWidth = destAsPort.getWidthSpec(); + + // FIXME: Support banks (containers) + var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + + sourceAsPort.getName() + + ((sourceWidth != null)? "[i]" : ""); + var dest = (destContainer != null ? destContainer.getName() + "." : "") + + destAsPort.getName() + + ((destWidth != null)? "[i]" : ""); + // If either side is a multiport, iterate. + // Note that one side could be a multiport of width 1 and the other an ordinary port. + var result = new StringBuilder(); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceAsPort.getWidthSpec() != null) { + var width = (sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName(); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); + } else { + var width = (destContainer != null)? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName(); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); + } + } + result.append("lf_set(" + dest + ", " + source + "->value);"); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + result.append(" }"); + } + return result.toString(); } /** Set the scheduler type in the target config as needed. */ diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 854c8f108a..5f76ab7184 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -59,6 +59,7 @@ import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -539,7 +540,13 @@ protected void generateSelfStructExtension( } @Override - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { + protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { + var source = + (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") + + sourceRef.getVariable().getName(); + var dest = + (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") + + destRef.getVariable().getName(); // NOTE: Strangely, a newline is needed at the beginning or indentation // gets swallowed. return String.join( diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 693c5f5bdb..184567d3bd 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 693c5f5bdbc6918cebc619c3ae46a22af719b741 +Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 diff --git a/test/C/src/modal_models/ModalMultiport.lf b/test/C/src/modal_models/ModalMultiport.lf new file mode 100644 index 0000000000..e6714ec024 --- /dev/null +++ b/test/C/src/modal_models/ModalMultiport.lf @@ -0,0 +1,67 @@ +target C { + timeout: 1 ms +} + +reactor Destination(n_inputs: int = 2) { + input[n_inputs] req: int + output[n_inputs] rsp: int + + reaction(req) -> rsp {= + for (int i = 0; i < self->n_inputs; ++i) { + if (req[i]->is_present) { + lf_set (rsp[i], req[i]->value); + } + } + =} +} + +reactor Source(n_ports: int = 2) { + output[n_ports] req: int + input[n_ports] rsp: int + timer t(0, 1 ms) + + reaction(t) -> req {= + for (int i = 0; i < self->n_ports; ++i) { + lf_set (req[i], i); + } + =} + + reaction(rsp) {= + for (int i = 0; i < self->n_ports; ++i) { + lf_print("Received response:%d", rsp[i]->value); + if (rsp[i]->value != i) { + lf_print_error_and_exit("Expected %d", i); + } + } + =} +} + +reactor Selector(n_ports: int = 2) { + input[n_ports] in_req: int + output[n_ports] out_rsp: int + + initial mode DST_1 { + dst1 = new Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + lf_set_mode(DST_2); + =} + } + + mode DST_2 { + dst2 = new Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From d6da2b66e211c649401b0dd286de1fd1008f091f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 11:42:03 -0700 Subject: [PATCH 069/136] Added Python support --- .../org/lflang/generator/c/CGenerator.java | 14 ++---- .../generator/python/PythonGenerator.java | 50 +++++++++++-------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index d9436371e4..34e61691f7 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,7 +656,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (containers) + // FIXME: Support banks (for the containers) var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() + ((sourceWidth != null)? "[i]" : ""); @@ -667,15 +667,11 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - if (sourceAsPort.getWidthSpec() != null) { - var width = (sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName(); + var width = (sourceAsPort.getWidthSpec() != null)? + ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() : sourceAsPort.getName()) + : + ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() : destAsPort.getName()); result.append("for(int i = 0; i < " + width + "_width; i++) { "); - } else { - var width = (destContainer != null)? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName(); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); - } } result.append("lf_set(" + dest + ", " + source + "->value);"); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 5f76ab7184..214b0f6d41 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -52,14 +52,7 @@ import org.lflang.generator.c.CUtil; import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.generator.docker.PythonDockerGenerator; -import org.lflang.lf.Action; -import org.lflang.lf.Input; -import org.lflang.lf.Model; -import org.lflang.lf.Output; -import org.lflang.lf.Port; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; -import org.lflang.lf.VarRef; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -541,19 +534,34 @@ protected void generateSelfStructExtension( @Override protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { - var source = - (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") - + sourceRef.getVariable().getName(); - var dest = - (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") - + destRef.getVariable().getName(); - // NOTE: Strangely, a newline is needed at the beginning or indentation - // gets swallowed. - return String.join( - "\n", - "\n# Generated forwarding reaction for connections with the same destination", - "# but located in mutually exclusive modes.", - dest + ".set(" + source + ".value)\n"); + Instantiation sourceContainer = sourceRef.getContainer(); + Instantiation destContainer = destRef.getContainer(); + Port sourceAsPort = (Port) sourceRef.getVariable(); + Port destAsPort = (Port) destRef.getVariable(); + WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); + WidthSpec destWidth = destAsPort.getWidthSpec(); + + // FIXME: Support banks (for the containers) + var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + + sourceAsPort.getName() + + ((sourceWidth != null)? "[i]" : ""); + var dest = (destContainer != null ? destContainer.getName() + "." : "") + + destAsPort.getName() + + ((destWidth != null)? "[i]" : ""); + // If either side is a multiport, iterate. + // Note that one side could be a multiport of width 1 and the other an ordinary port. + var result = new StringBuilder(); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + var width = (sourceAsPort.getWidthSpec() != null)? + ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : + ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for i in range(" + width + ".width): "); + } + result.append(dest + ".set(" + source + ".value)"); + return result.toString(); } @Override From ae8c1ab86a0ada06d9234503fa0e0e32d1a21b20 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 11:50:00 -0700 Subject: [PATCH 070/136] Spotless --- .../org/lflang/generator/c/CGenerator.java | 24 ++++++++++------- .../generator/python/PythonGenerator.java | 26 +++++++++++-------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 34e61691f7..f9c89ac1d4 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -657,21 +657,27 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec destWidth = destAsPort.getWidthSpec(); // FIXME: Support banks (for the containers) - var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + var source = + (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() - + ((sourceWidth != null)? "[i]" : ""); - var dest = (destContainer != null ? destContainer.getName() + "." : "") + + ((sourceWidth != null) ? "[i]" : ""); + var dest = + (destContainer != null ? destContainer.getName() + "." : "") + destAsPort.getName() - + ((destWidth != null)? "[i]" : ""); + + ((destWidth != null) ? "[i]" : ""); // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - var width = (sourceAsPort.getWidthSpec() != null)? - ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() : sourceAsPort.getName()) - : - ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() : destAsPort.getName()); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); + var width = + (sourceAsPort.getWidthSpec() != null) + ? ((sourceContainer != null) + ? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : ((destContainer != null) + ? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); } result.append("lf_set(" + dest + ", " + source + "->value);"); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 214b0f6d41..64839bc347 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -542,23 +542,27 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec destWidth = destAsPort.getWidthSpec(); // FIXME: Support banks (for the containers) - var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + var source = + (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() - + ((sourceWidth != null)? "[i]" : ""); - var dest = (destContainer != null ? destContainer.getName() + "." : "") + + ((sourceWidth != null) ? "[i]" : ""); + var dest = + (destContainer != null ? destContainer.getName() + "." : "") + destAsPort.getName() - + ((destWidth != null)? "[i]" : ""); + + ((destWidth != null) ? "[i]" : ""); // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - var width = (sourceAsPort.getWidthSpec() != null)? - ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : - ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); - result.append("for i in range(" + width + ".width): "); + var width = + (sourceAsPort.getWidthSpec() != null) + ? ((sourceContainer != null) + ? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : ((destContainer != null) + ? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for i in range(" + width + ".width): "); } result.append(dest + ".set(" + source + ".value)"); return result.toString(); From 9614b9dccf4765aa3d62eede5ca15c4a08dbb17e Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 17:38:41 -0700 Subject: [PATCH 071/136] Compile error with banks/modes/multiports --- core/src/main/java/org/lflang/generator/c/CGenerator.java | 2 +- .../main/java/org/lflang/generator/c/CReactionGenerator.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index f9c89ac1d4..d3150a982a 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -668,7 +668,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); - if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceWidth != null || destWidth != null) { var width = (sourceAsPort.getWidthSpec() != null) ? ((sourceContainer != null) diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index 151d2a47fb..ffc36848fe 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -279,7 +279,9 @@ public static int maxContainedReactorBankWidth( nestedBreadcrumbs.add(mainDef); } int result = max; - Reactor parent = (Reactor) containedReactor.eContainer(); + Reactor parent = containedReactor.eContainer() instanceof Mode? + (Reactor) containedReactor.eContainer().eContainer() + : (Reactor) containedReactor.eContainer(); if (parent == ASTUtils.toDefinition(mainDef.getReactorClass())) { // The parent is main, so there can't be any other instantiations of it. return ASTUtils.width(containedReactor.getWidthSpec(), null); From 11b4ff5ac54bd9f1a032de75df49cc51769e5ffe Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 19:07:40 -0700 Subject: [PATCH 072/136] Support banks with multiports in modes --- .../org/lflang/generator/c/CGenerator.java | 61 +++++++++++++---- .../generator/c/CReactionGenerator.java | 5 +- test/C/src/modal_models/ModalMultiportBank.lf | 67 +++++++++++++++++++ 3 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 test/C/src/modal_models/ModalMultiportBank.lf diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index d3150a982a..8ff50ca999 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,33 +656,68 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (for the containers) + // If the source or dest is a port of a bank, we need to iterate over it. + var isBank = false; + Instantiation bank = null; + var sourceContainerRef = ""; + if (sourceContainer != null) { + sourceContainerRef = sourceContainer.getName() + "."; + bank = sourceContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + sourceContainerRef = sourceContainer.getName() + "[j]."; + } + } + var sourceIndex = isBank ? "i" : "count"; var source = - (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceContainerRef + sourceAsPort.getName() - + ((sourceWidth != null) ? "[i]" : ""); + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + var destContainerRef = ""; + var destIndex = "count"; + if (destContainer != null) { + destIndex = "i"; + destContainerRef = destContainer.getName() + "."; + if (bank == null) { + bank = destContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + destContainerRef = destContainer.getName() + "[j]."; + } + } + } var dest = - (destContainer != null ? destContainer.getName() + "." : "") + destContainerRef + destAsPort.getName() - + ((destWidth != null) ? "[i]" : ""); + + ((destWidth != null) ? "[" + destIndex + "]" : ""); + var result = new StringBuilder(); + result.append("{ int count = 0; SUPPRESS_UNUSED_WARNING(count); "); + // If either side is a bank (only one side should be), iterate over it. + if (isBank) { + var width = new StringBuilder(); + for (var term : bank.getWidthSpec().getTerms()) { + if (!width.isEmpty()) width.append(" + "); + if (term.getCode() != null) width.append(term.getCode().getBody()); + else if (term.getParameter() != null) width.append("self->" + term.getParameter()); + else width.append(term.getWidth()); + } + result.append("for(int j = 0; j < " + width.toString() + "; j++) { "); + } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. - var result = new StringBuilder(); if (sourceWidth != null || destWidth != null) { var width = (sourceAsPort.getWidthSpec() != null) - ? ((sourceContainer != null) - ? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : ((destContainer != null) - ? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); result.append("for(int i = 0; i < " + width + "_width; i++) { "); } - result.append("lf_set(" + dest + ", " + source + "->value);"); + result.append("lf_set(" + dest + ", " + source + "->value); count++; "); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { result.append(" }"); } + if (isBank) result.append(" }"); + result.append(" }"); return result.toString(); } diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index ffc36848fe..a2f2a93f7d 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -279,8 +279,9 @@ public static int maxContainedReactorBankWidth( nestedBreadcrumbs.add(mainDef); } int result = max; - Reactor parent = containedReactor.eContainer() instanceof Mode? - (Reactor) containedReactor.eContainer().eContainer() + Reactor parent = + containedReactor.eContainer() instanceof Mode + ? (Reactor) containedReactor.eContainer().eContainer() : (Reactor) containedReactor.eContainer(); if (parent == ASTUtils.toDefinition(mainDef.getReactorClass())) { // The parent is main, so there can't be any other instantiations of it. diff --git a/test/C/src/modal_models/ModalMultiportBank.lf b/test/C/src/modal_models/ModalMultiportBank.lf new file mode 100644 index 0000000000..9ab4213fd5 --- /dev/null +++ b/test/C/src/modal_models/ModalMultiportBank.lf @@ -0,0 +1,67 @@ +target C { + timeout: 1 ms +} + +reactor Destination(n_inputs: int = 2) { + input[n_inputs] req: int + output[n_inputs] rsp: int + + reaction(req) -> rsp {= + for (int i = 0; i < self->n_inputs; ++i) { + if (req[i]->is_present) { + lf_set (rsp[i], req[i]->value); + } + } + =} +} + +reactor Source(n_ports: int = 4) { + output[n_ports] req: int + input[n_ports] rsp: int + timer t(0, 1 ms) + + reaction(t) -> req {= + for (int i = 0; i < self->n_ports; ++i) { + lf_set (req[i], i); + } + =} + + reaction(rsp) {= + for (int i = 0; i < self->n_ports; ++i) { + lf_print("Received response:%d", rsp[i]->value); + if (rsp[i]->value != i) { + lf_print_error_and_exit("Expected %d", i); + } + } + =} +} + +reactor Selector(n_ports: int = 4) { + input[n_ports] in_req: int + output[n_ports] out_rsp: int + + initial mode DST_1 { + dst1 = new[2] Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + lf_set_mode(DST_2); + =} + } + + mode DST_2 { + dst2 = new[2] Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From 460eb50f0937f3c51b09feccbc21b7be7fa55262 Mon Sep 17 00:00:00 2001 From: Depetrol Date: Sun, 6 Oct 2024 22:52:13 -0700 Subject: [PATCH 073/136] only lowercase forever literal --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- core/src/main/java/org/lflang/ast/ASTUtils.java | 8 +++----- test/Python/src/federated/Dataflow.lf | 10 +++++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 11275cc82f..b3421a37be 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,7 +393,7 @@ SignedInt: ; Forever: - 'FOREVER' | 'forever' + 'forever' ; Literal: diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index a7e1c80595..24be720870 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -948,11 +948,10 @@ public static boolean isZero(String literal) { * Report whether the given literal is forever or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code FOREVER} or {@code forever}, - * false otherwise. + * @return True if the given literal denotes the constant {@code forever}, false otherwise. */ public static boolean isForever(String literal) { - return literal != null && (literal.equals("FOREVER") || literal.equals("forever")); + return literal != null && literal.equals("forever"); } /** @@ -972,8 +971,7 @@ public static boolean isZero(Expression expr) { * Report whether the given expression is forever or not. * * @param expr AST node to inspect. - * @return True if the given value denotes the constant {@code FOREVER} or {@code forever}, false - * otherwise. + * @return True if the given value denotes the constant {@code forever}, false otherwise. */ public static boolean isForever(Expression expr) { if (expr instanceof Literal) { diff --git a/test/Python/src/federated/Dataflow.lf b/test/Python/src/federated/Dataflow.lf index 892af49649..fb6625abde 100644 --- a/test/Python/src/federated/Dataflow.lf +++ b/test/Python/src/federated/Dataflow.lf @@ -6,7 +6,7 @@ preamble {= import time =} -reactor Client(STA=FOREVER) { +reactor Client(STA=forever) { input server_message output client_message @@ -24,13 +24,13 @@ reactor Client(STA=FOREVER) { request_stop() # Need to unconditionally produce output or downstream could lock up waiting for it. client_message.set(val) - =} STP(FOREVER) {= + =} STP(forever) {= print("Client STAA Violated!") exit(1) =} } -reactor Server(STA=FOREVER) { +reactor Server(STA=forever) { output server_message input client_message1 input client_message2 @@ -51,13 +51,13 @@ reactor Server(STA=FOREVER) { request_stop() # Need to unconditionally produce output or downstream could lock up waiting for it. server_message.set(val) - =} STP(FOREVER) {= + =} STP(forever) {= print("Server STAA Violated!") exit(1) =} } -federated reactor(STA=FOREVER) { +federated reactor(STA=forever) { client1 = new Client() client2 = new Client() server = new Server() From 2d5abf8e81b4b27ed959a1ed4d7ac4f8aae4d8d7 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 7 Oct 2024 08:20:18 -0700 Subject: [PATCH 074/136] Rename local vars to prevent collision with port names --- .../org/lflang/generator/c/CGenerator.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 8ff50ca999..e9327c52f3 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,6 +656,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); + // NOTE: Have to be careful with naming count variables because if the name matches + // that of a port, the program will fail to compile. + // If the source or dest is a port of a bank, we need to iterate over it. var isBank = false; Instantiation bank = null; @@ -665,24 +668,24 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, bank = sourceContainer; if (bank.getWidthSpec() != null) { isBank = true; - sourceContainerRef = sourceContainer.getName() + "[j]."; + sourceContainerRef = sourceContainer.getName() + "[_lf_j]."; } } - var sourceIndex = isBank ? "i" : "count"; + var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = sourceContainerRef + sourceAsPort.getName() + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); var destContainerRef = ""; - var destIndex = "count"; + var destIndex = "_lf_c"; if (destContainer != null) { - destIndex = "i"; + destIndex = "_lf_i"; destContainerRef = destContainer.getName() + "."; if (bank == null) { bank = destContainer; if (bank.getWidthSpec() != null) { isBank = true; - destContainerRef = destContainer.getName() + "[j]."; + destContainerRef = destContainer.getName() + "[_lf_j]."; } } } @@ -691,7 +694,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, + destAsPort.getName() + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new StringBuilder(); - result.append("{ int count = 0; SUPPRESS_UNUSED_WARNING(count); "); + result.append("{ int _lf_c = 0; SUPPRESS_UNUSED_WARNING(_lf_c); "); // If either side is a bank (only one side should be), iterate over it. if (isBank) { var width = new StringBuilder(); @@ -701,7 +704,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, else if (term.getParameter() != null) width.append("self->" + term.getParameter()); else width.append(term.getWidth()); } - result.append("for(int j = 0; j < " + width.toString() + "; j++) { "); + result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. @@ -710,9 +713,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, (sourceAsPort.getWidthSpec() != null) ? sourceContainerRef + sourceAsPort.getName() : destContainerRef + destAsPort.getName(); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); + result.append("for(int _lf_i = 0; _lf_i < " + width + "_width; _lf_i++) { "); } - result.append("lf_set(" + dest + ", " + source + "->value); count++; "); + result.append("lf_set(" + dest + ", " + source + "->value); _lf_c++; "); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { result.append(" }"); } From b29f02991a07fad64eb78c7de54206556b44854e Mon Sep 17 00:00:00 2001 From: depetrol Date: Mon, 7 Oct 2024 10:10:02 -0700 Subject: [PATCH 075/136] fix --- core/src/main/java/org/lflang/generator/TargetTypes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index 4291cdc45e..24ef724283 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -176,7 +176,7 @@ default String getTargetInitializer(Initializer init, Type type) { default String getTargetExpr(Expression expr, InferredType type) { if (ASTUtils.isZero(expr) && type != null && type.isTime) { return getTargetTimeExpr(TimeValue.ZERO); - } else if (ASTUtils.isForever(expr) && type != null && type.isTime) { + } else if (ASTUtils.isForever(expr) && type != null) { return getTargetTimeExpr(TimeValue.MAX_VALUE); } else if (expr instanceof ParameterReference) { return getTargetParamRef((ParameterReference) expr, type); From 36b6922ce0a2b9b34229ac801c3723f8f5bbf236 Mon Sep 17 00:00:00 2001 From: Depetrol Date: Mon, 7 Oct 2024 22:16:35 -0700 Subject: [PATCH 076/136] fix: add forever to token --- core/src/main/java/org/lflang/LinguaFranca.xtext | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index b3421a37be..5aa9b1b51c 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -525,7 +525,7 @@ Token: 'startup' | 'shutdown' | 'after' | 'deadline' | 'mutation' | 'preamble' | 'new' | 'federated' | 'at' | 'as' | 'from' | 'widthof' | 'const' | 'method' | 'interleaved' | 'mode' | 'initial' | 'reset' | 'history' | 'watchdog' | - 'extends' | + 'extends' | 'forever' | // Other terminals NEGINT | TRUE | FALSE | From c04cc4026f3133f1e7627599adff0f5ab4fa0fcc Mon Sep 17 00:00:00 2001 From: Depetrol Date: Mon, 7 Oct 2024 22:47:53 -0700 Subject: [PATCH 077/136] feat: introduce never time literal --- .../main/java/org/lflang/LinguaFranca.xtext | 10 ++++--- core/src/main/java/org/lflang/TimeValue.java | 3 +++ .../main/java/org/lflang/ast/ASTUtils.java | 26 +++++++++++++++++++ .../org/lflang/generator/TargetTypes.java | 3 +++ .../org/lflang/validation/LFValidator.java | 8 ++++++ test/C/src/LastTimeDefer.lf | 8 +----- test/C/src/LastTimeDrop.lf | 8 +----- test/C/src/LastTimeReplace.lf | 8 +----- 8 files changed, 50 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 5aa9b1b51c..1cbfa9d282 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -339,7 +339,7 @@ ParameterReference: ; Time: - (interval=INT unit=TimeUnit) + (interval=INT unit=TimeUnit) | Forever | Never ; Port: @@ -396,8 +396,12 @@ Forever: 'forever' ; +Never: + 'never' +; + Literal: - STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean | Forever + STRING | CHAR_LIT | SignedFloat | SignedInt | Boolean | Forever | Never ; Boolean: @@ -525,7 +529,7 @@ Token: 'startup' | 'shutdown' | 'after' | 'deadline' | 'mutation' | 'preamble' | 'new' | 'federated' | 'at' | 'as' | 'from' | 'widthof' | 'const' | 'method' | 'interleaved' | 'mode' | 'initial' | 'reset' | 'history' | 'watchdog' | - 'extends' | 'forever' | + 'extends' | 'forever' | 'never' | // Other terminals NEGINT | TRUE | FALSE | diff --git a/core/src/main/java/org/lflang/TimeValue.java b/core/src/main/java/org/lflang/TimeValue.java index f393544c5a..832e9c754b 100644 --- a/core/src/main/java/org/lflang/TimeValue.java +++ b/core/src/main/java/org/lflang/TimeValue.java @@ -36,6 +36,9 @@ public final class TimeValue implements Comparable { /** The maximum value of this type. This is approximately equal to 292 years. */ public static final TimeValue MAX_VALUE = new TimeValue(Long.MAX_VALUE, TimeUnit.NANO); + /** The minimum value of this type. */ + public static final TimeValue MIN_VALUE = new TimeValue(Long.MIN_VALUE, TimeUnit.NANO); + /** A time value equal to zero. */ public static final TimeValue ZERO = new TimeValue(0, null); diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 24be720870..a7cb5eefa3 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -954,6 +954,17 @@ public static boolean isForever(String literal) { return literal != null && literal.equals("forever"); } + + /** + * Report whether the given literal is never or not. + * + * @param literal AST node to inspect. + * @return True if the given literal denotes the constant {@code never}, false otherwise. + */ + public static boolean isNever(String literal) { + return literal != null && literal.equals("never"); + } + /** * Report whether the given expression is zero or not. * @@ -980,6 +991,19 @@ public static boolean isForever(Expression expr) { return false; } + /** + * Report whether the given expression is never or not. + * + * @param expr AST node to inspect. + * @return True if the given value denotes the constant {@code never}, false otherwise. + */ + public static boolean isNever(Expression expr) { + if (expr instanceof Literal) { + return isNever(((Literal) expr).getLiteral()); + } + return false; + } + /** * Report whether the given string literal is an integer number or not. * @@ -1162,6 +1186,8 @@ public static TimeValue getLiteralTimeValue(Expression expr) { return TimeValue.ZERO; } else if (expr instanceof Literal && isForever(((Literal) expr).getLiteral())) { return TimeValue.MAX_VALUE; + } else if (expr instanceof Literal && isNever(((Literal) expr).getLiteral())) { + return TimeValue.MIN_VALUE; } else { return null; } diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index 24ef724283..59e2570047 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.stream.Collectors; + import org.lflang.InferredType; import org.lflang.TimeValue; import org.lflang.ast.ASTUtils; @@ -178,6 +179,8 @@ default String getTargetExpr(Expression expr, InferredType type) { return getTargetTimeExpr(TimeValue.ZERO); } else if (ASTUtils.isForever(expr) && type != null) { return getTargetTimeExpr(TimeValue.MAX_VALUE); + } else if (ASTUtils.isNever(expr) && type != null) { + return getTargetTimeExpr(TimeValue.MIN_VALUE); } else if (expr instanceof ParameterReference) { return getTargetParamRef((ParameterReference) expr, type); } else if (expr instanceof Time) { diff --git a/core/src/main/java/org/lflang/validation/LFValidator.java b/core/src/main/java/org/lflang/validation/LFValidator.java index 4c5f87fc6a..eb721cf032 100644 --- a/core/src/main/java/org/lflang/validation/LFValidator.java +++ b/core/src/main/java/org/lflang/validation/LFValidator.java @@ -1594,6 +1594,14 @@ private void checkExpressionIsTime(Expression value, EStructuralFeature feature) return; } + if (ASTUtils.isForever(((Literal) value).getLiteral())) { + return; + } + + if (ASTUtils.isNever(((Literal) value).getLiteral())) { + return; + } + if (ASTUtils.isInteger(((Literal) value).getLiteral())) { error("Missing time unit.", feature); return; diff --git a/test/C/src/LastTimeDefer.lf b/test/C/src/LastTimeDefer.lf index 2509a5e896..65001bdc9c 100644 --- a/test/C/src/LastTimeDefer.lf +++ b/test/C/src/LastTimeDefer.lf @@ -9,13 +9,7 @@ main reactor { logical action a(1 ms, 300 ms): int state c: int = 0 state c2: int = 0 // For expected values. - state last: time = 0 - - reaction(startup) {= - // Unfortunately, a time state variable cannot be initialized with NEVER. - // So we do that here. - self->last = NEVER; - =} + state last: time = never reaction(t) -> a {= tag_t now = lf_tag(); diff --git a/test/C/src/LastTimeDrop.lf b/test/C/src/LastTimeDrop.lf index 2862ac75f0..5cfc7c2ad2 100644 --- a/test/C/src/LastTimeDrop.lf +++ b/test/C/src/LastTimeDrop.lf @@ -8,13 +8,7 @@ main reactor { timer t(0, 100 ms) logical action a(1 ms, 300 ms, "drop"): int state c: int = 0 - state last: time = 0 - - reaction(startup) {= - // Unfortunately, a time state variable cannot be initialized with NEVER. - // So we do that here. - self->last = NEVER; - =} + state last: time = never reaction(t) -> a {= tag_t now = lf_tag(); diff --git a/test/C/src/LastTimeReplace.lf b/test/C/src/LastTimeReplace.lf index 0d44bb58b5..51b29f972a 100644 --- a/test/C/src/LastTimeReplace.lf +++ b/test/C/src/LastTimeReplace.lf @@ -8,13 +8,7 @@ main reactor { timer t(0, 100 ms) logical action a(1 ms, 300 ms, "replace"): int state c: int = 0 - state last: time = 0 - - reaction(startup) {= - // Unfortunately, a time state variable cannot be initialized with NEVER. - // So we do that here. - self->last = NEVER; - =} + state last: time = never reaction(t) -> a {= tag_t now = lf_tag(); From eceb36708c13142eeee30388e94af6dc825ec540 Mon Sep 17 00:00:00 2001 From: Depetrol Date: Mon, 7 Oct 2024 23:04:33 -0700 Subject: [PATCH 078/136] feat: allow FOREVER and NEVER --- core/src/main/java/org/lflang/LinguaFranca.xtext | 8 ++++---- core/src/main/java/org/lflang/ast/ASTUtils.java | 15 ++++++++------- .../java/org/lflang/generator/TargetTypes.java | 3 +-- .../C/src/modal_models/BanksCount3ModesComplex.lf | 6 +++--- test/C/src/modal_models/ModalNestedReactions.lf | 8 ++++---- .../src/modal_models/BanksCount3ModesComplex.lf | 6 +++--- .../src/modal_models/ModalNestedReactions.lf | 8 ++++---- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 1cbfa9d282..09401074a6 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -339,7 +339,7 @@ ParameterReference: ; Time: - (interval=INT unit=TimeUnit) | Forever | Never + (interval=INT unit=TimeUnit) ; Port: @@ -393,11 +393,11 @@ SignedInt: ; Forever: - 'forever' + 'forever' | 'FOREVER' ; Never: - 'never' + 'never' | 'NEVER' ; Literal: @@ -529,7 +529,7 @@ Token: 'startup' | 'shutdown' | 'after' | 'deadline' | 'mutation' | 'preamble' | 'new' | 'federated' | 'at' | 'as' | 'from' | 'widthof' | 'const' | 'method' | 'interleaved' | 'mode' | 'initial' | 'reset' | 'history' | 'watchdog' | - 'extends' | 'forever' | 'never' | + 'extends' | 'forever' | 'FOREVER' | 'never' | 'NEVER' | // Other terminals NEGINT | TRUE | FALSE | diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index a7cb5eefa3..5cd0be1129 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -948,23 +948,24 @@ public static boolean isZero(String literal) { * Report whether the given literal is forever or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code forever}, false otherwise. + * @return True if the given literal denotes the constant {@code forever} or {@code FOREVER}, + * false otherwise. */ public static boolean isForever(String literal) { - return literal != null && literal.equals("forever"); + return literal != null && (literal.equals("forever") || literal.equals("FOREVER")); } - /** * Report whether the given literal is never or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code never}, false otherwise. + * @return True if the given literal denotes the constant {@code never} or {@code NEVER}, false + * otherwise. */ public static boolean isNever(String literal) { - return literal != null && literal.equals("never"); + return literal != null && (literal.equals("never") || literal.equals("NEVER")); } - + /** * Report whether the given expression is zero or not. * @@ -1187,7 +1188,7 @@ public static TimeValue getLiteralTimeValue(Expression expr) { } else if (expr instanceof Literal && isForever(((Literal) expr).getLiteral())) { return TimeValue.MAX_VALUE; } else if (expr instanceof Literal && isNever(((Literal) expr).getLiteral())) { - return TimeValue.MIN_VALUE; + return TimeValue.MIN_VALUE; } else { return null; } diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index 59e2570047..42d3e62064 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.stream.Collectors; - import org.lflang.InferredType; import org.lflang.TimeValue; import org.lflang.ast.ASTUtils; @@ -180,7 +179,7 @@ default String getTargetExpr(Expression expr, InferredType type) { } else if (ASTUtils.isForever(expr) && type != null) { return getTargetTimeExpr(TimeValue.MAX_VALUE); } else if (ASTUtils.isNever(expr) && type != null) { - return getTargetTimeExpr(TimeValue.MIN_VALUE); + return getTargetTimeExpr(TimeValue.MIN_VALUE); } else if (expr instanceof ParameterReference) { return getTargetParamRef((ParameterReference) expr, type); } else if (expr instanceof Time) { diff --git a/test/C/src/modal_models/BanksCount3ModesComplex.lf b/test/C/src/modal_models/BanksCount3ModesComplex.lf index 48774e0b80..1385573be0 100644 --- a/test/C/src/modal_models/BanksCount3ModesComplex.lf +++ b/test/C/src/modal_models/BanksCount3ModesComplex.lf @@ -12,7 +12,7 @@ reactor MetaCounter { output[2] always: int output[2] mode1: int output[2] mode2: int - output[2] never: int + output[2] neverp: int outer_counters = new[2] CounterCycle() (next)+ -> outer_counters.next @@ -46,7 +46,7 @@ reactor MetaCounter { mode3_counters = new[2] CounterCycle() (next)+ -> mode3_counters.next - mode3_counters.count -> never + mode3_counters.count -> neverp } } @@ -72,7 +72,7 @@ main reactor { 250000000,1,1,1,1,1,1,1,1,0,3,0,3,0,3,0,3,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 }, training = false) - counters.always, counters.mode1, counters.mode2, counters.never -> test.events + counters.always, counters.mode1, counters.mode2, counters.neverp -> test.events // Trigger reaction(stepper) -> counters.next {= diff --git a/test/C/src/modal_models/ModalNestedReactions.lf b/test/C/src/modal_models/ModalNestedReactions.lf index 88bb61c8bb..90b04674ce 100644 --- a/test/C/src/modal_models/ModalNestedReactions.lf +++ b/test/C/src/modal_models/ModalNestedReactions.lf @@ -9,7 +9,7 @@ reactor CounterCycle { output count: int output only_in_two: bool - output never: int + output neverp: int initial mode One { reaction(next) -> count, reset(Two) {= @@ -29,8 +29,8 @@ reactor CounterCycle { } mode Three { - reaction(next) -> never {= - lf_set(never, true); + reaction(next) -> neverp {= + lf_set(neverp, true); =} } } @@ -69,7 +69,7 @@ main reactor { } =} - reaction(counter.never) {= + reaction(counter.neverp) {= printf("ERROR: Detected output from unreachable mode.\n"); exit(4); =} diff --git a/test/Python/src/modal_models/BanksCount3ModesComplex.lf b/test/Python/src/modal_models/BanksCount3ModesComplex.lf index 77b8461861..fde46b539c 100644 --- a/test/Python/src/modal_models/BanksCount3ModesComplex.lf +++ b/test/Python/src/modal_models/BanksCount3ModesComplex.lf @@ -12,7 +12,7 @@ reactor MetaCounter { output[2] always output[2] mode1 output[2] mode2 - output[2] never + output[2] neverp outer_counters = new[2] CounterCycle() (next)+ -> outer_counters.next @@ -46,7 +46,7 @@ reactor MetaCounter { mode3_counters = new[2] CounterCycle() (next)+ -> mode3_counters.next - mode3_counters.count -> never + mode3_counters.count -> neverp } } @@ -69,7 +69,7 @@ main reactor { 250000000,1,1,1,1,1,1,1,1,0,3,0,3,0,3,0,3,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 ], training = False) - counters.always, counters.mode1, counters.mode2, counters.never -> test.events + counters.always, counters.mode1, counters.mode2, counters.neverp -> test.events # Trigger reaction(stepper) -> counters.next {= diff --git a/test/Python/src/modal_models/ModalNestedReactions.lf b/test/Python/src/modal_models/ModalNestedReactions.lf index a3b89c997a..5ce8f1b529 100644 --- a/test/Python/src/modal_models/ModalNestedReactions.lf +++ b/test/Python/src/modal_models/ModalNestedReactions.lf @@ -9,7 +9,7 @@ reactor CounterCycle { output count output only_in_two - output never + output neverp initial mode One { reaction(next) -> count, reset(Two) {= @@ -29,8 +29,8 @@ reactor CounterCycle { } mode Three { - reaction(next) -> never {= - never.set(True) + reaction(next) -> neverp {= + neverp.set(True) =} } } @@ -68,7 +68,7 @@ main reactor { exit(3) =} - reaction(counter.never) {= + reaction(counter.neverp) {= sys.stderr.write("ERROR: Detected output from unreachable mode.\n") exit(4) =} From de7723cec2f73d46c532094158cfd04c0c5e23fd Mon Sep 17 00:00:00 2001 From: Depetrol Date: Tue, 8 Oct 2024 08:49:42 -0700 Subject: [PATCH 079/136] revert allow FOREVER and NEVER --- core/src/main/java/org/lflang/LinguaFranca.xtext | 6 +++--- core/src/main/java/org/lflang/ast/ASTUtils.java | 10 ++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/lflang/LinguaFranca.xtext b/core/src/main/java/org/lflang/LinguaFranca.xtext index 09401074a6..103224e23c 100644 --- a/core/src/main/java/org/lflang/LinguaFranca.xtext +++ b/core/src/main/java/org/lflang/LinguaFranca.xtext @@ -393,11 +393,11 @@ SignedInt: ; Forever: - 'forever' | 'FOREVER' + 'forever' ; Never: - 'never' | 'NEVER' + 'never' ; Literal: @@ -529,7 +529,7 @@ Token: 'startup' | 'shutdown' | 'after' | 'deadline' | 'mutation' | 'preamble' | 'new' | 'federated' | 'at' | 'as' | 'from' | 'widthof' | 'const' | 'method' | 'interleaved' | 'mode' | 'initial' | 'reset' | 'history' | 'watchdog' | - 'extends' | 'forever' | 'FOREVER' | 'never' | 'NEVER' | + 'extends' | 'forever' | 'never' | // Other terminals NEGINT | TRUE | FALSE | diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 5cd0be1129..7e55e3cabc 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -948,22 +948,20 @@ public static boolean isZero(String literal) { * Report whether the given literal is forever or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code forever} or {@code FOREVER}, - * false otherwise. + * @return True if the given literal denotes the constant {@code forever}, false otherwise. */ public static boolean isForever(String literal) { - return literal != null && (literal.equals("forever") || literal.equals("FOREVER")); + return literal != null && literal.equals("forever"); } /** * Report whether the given literal is never or not. * * @param literal AST node to inspect. - * @return True if the given literal denotes the constant {@code never} or {@code NEVER}, false - * otherwise. + * @return True if the given literal denotes the constant {@code never}, false otherwise. */ public static boolean isNever(String literal) { - return literal != null && (literal.equals("never") || literal.equals("NEVER")); + return literal != null && literal.equals("never"); } /** From dd53b50ae51b9789af7321a4ae04cbd3a234ad8d Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Tue, 8 Oct 2024 22:53:29 -0700 Subject: [PATCH 080/136] Update reactor-c submodule --- core/src/main/resources/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 693c5f5bdb..a370377150 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 693c5f5bdbc6918cebc619c3ae46a22af719b741 +Subproject commit a37037715026caceab6a6e62b94fdf52d8509c06 From 1249f1445fceb460d8c40f8a15278cfb54debb42 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 14:19:43 -0700 Subject: [PATCH 081/136] Fixed imports to not use * --- .../org/lflang/generator/GeneratorBase.java | 9 +++++++- .../org/lflang/generator/c/CGenerator.java | 15 +++++++++++- .../generator/python/PythonGenerator.java | 23 ++++++++----------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/GeneratorBase.java b/core/src/main/java/org/lflang/generator/GeneratorBase.java index b3ef1a6491..83eb540775 100644 --- a/core/src/main/java/org/lflang/generator/GeneratorBase.java +++ b/core/src/main/java/org/lflang/generator/GeneratorBase.java @@ -53,7 +53,14 @@ import org.lflang.generator.docker.DockerComposeGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.graph.InstantiationGraph; -import org.lflang.lf.*; +import org.lflang.lf.Attribute; +import org.lflang.lf.Connection; +import org.lflang.lf.Instantiation; +import org.lflang.lf.LfFactory; +import org.lflang.lf.Mode; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.FilesProperty; diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index e9327c52f3..c8fc99d2c5 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -70,7 +70,20 @@ import org.lflang.generator.docker.CDockerGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.generator.python.PythonGenerator; -import org.lflang.lf.*; +import org.lflang.lf.Action; +import org.lflang.lf.ActionOrigin; +import org.lflang.lf.Input; +import org.lflang.lf.Instantiation; +import org.lflang.lf.Mode; +import org.lflang.lf.Port; +import org.lflang.lf.Preamble; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.ReactorDecl; +import org.lflang.lf.StateVar; +import org.lflang.lf.Variable; +import org.lflang.lf.VarRef; +import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.BuildCommandsProperty; diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 64839bc347..52620e2b2b 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -52,7 +52,16 @@ import org.lflang.generator.c.CUtil; import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.generator.docker.PythonDockerGenerator; -import org.lflang.lf.*; +import org.lflang.lf.Action; +import org.lflang.lf.Input; +import org.lflang.lf.Instantiation; +import org.lflang.lf.Model; +import org.lflang.lf.Output; +import org.lflang.lf.Port; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; +import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -641,18 +650,6 @@ private static String generateCmakeInstall(FileConfig fileConfig) { .replace("", pyMainName); } - /** - * Generate a ({@code key}, {@code val}) tuple pair for the {@code define_macros} field of the - * Extension class constructor from setuptools. - * - * @param key The key of the macro entry - * @param val The value of the macro entry - * @return A ({@code key}, {@code val}) tuple pair as String - */ - private static String generateMacroEntry(String key, String val) { - return "(" + StringUtil.addDoubleQuotes(key) + ", " + StringUtil.addDoubleQuotes(val) + ")"; - } - /** * Generate the name of the python module. * From f85f400a4828eec8847c8ef9d8a2f5abe599c39f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 15:59:09 -0700 Subject: [PATCH 082/136] Support in Python plus tests --- .../org/lflang/generator/c/CGenerator.java | 2 +- .../generator/python/PythonGenerator.java | 79 ++++++++++++++----- .../Python/src/modal_models/ModalMultiport.lf | 63 +++++++++++++++ .../src/modal_models/ModalMultiportBank.lf | 63 +++++++++++++++ 4 files changed, 188 insertions(+), 19 deletions(-) create mode 100644 test/Python/src/modal_models/ModalMultiport.lf create mode 100644 test/Python/src/modal_models/ModalMultiportBank.lf diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index c8fc99d2c5..44eaad8c68 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -714,7 +714,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); if (term.getCode() != null) width.append(term.getCode().getBody()); - else if (term.getParameter() != null) width.append("self->" + term.getParameter()); + else if (term.getParameter() != null) width.append("self->" + term.getParameter().getName()); else width.append(term.getWidth()); } result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 52620e2b2b..658c8e4955 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -550,30 +550,73 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (for the containers) + // NOTE: Have to be careful with naming count variables because if the name matches + // that of a port, the program will fail to compile. + + // If the source or dest is a port of a bank, we need to iterate over it. + var isBank = false; + Instantiation bank = null; + var sourceContainerRef = ""; + if (sourceContainer != null) { + sourceContainerRef = sourceContainer.getName() + "."; + bank = sourceContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + sourceContainerRef = sourceContainer.getName() + "[_lf_j]."; + } + } + var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = - (sourceContainer != null ? sourceContainer.getName() + "." : "") - + sourceAsPort.getName() - + ((sourceWidth != null) ? "[i]" : ""); + sourceContainerRef + + sourceAsPort.getName() + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + var destContainerRef = ""; + var destIndex = "_lf_c"; + if (destContainer != null) { + destIndex = "_lf_i"; + destContainerRef = destContainer.getName() + "."; + if (bank == null) { + bank = destContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + destContainerRef = destContainer.getName() + "[_lf_j]."; + } + } + } var dest = - (destContainer != null ? destContainer.getName() + "." : "") - + destAsPort.getName() - + ((destWidth != null) ? "[i]" : ""); + destContainerRef + + destAsPort.getName() + + ((destWidth != null) ? "[" + destIndex + "]" : ""); + var result = new CodeBuilder(); + // If either side is a bank (only one side should be), iterate over it. + if (isBank) { + result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. + var width = new StringBuilder(); + for (var term : bank.getWidthSpec().getTerms()) { + if (!width.isEmpty()) width.append(" + "); + if (term.getCode() != null) width.append(term.getCode().getBody()); + else if (term.getParameter() != null) width.append("self." + term.getParameter().getName()); + else width.append(term.getWidth()); + } + result.pr("for _lf_j in range(" + width + "):"); + result.indent(); + } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. - var result = new StringBuilder(); - if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceWidth != null || destWidth != null) { var width = - (sourceAsPort.getWidthSpec() != null) - ? ((sourceContainer != null) - ? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : ((destContainer != null) - ? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); - result.append("for i in range(" + width + ".width): "); + (sourceAsPort.getWidthSpec() != null) + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); + result.pr("for _lf_i in range(" + width + ".width):"); + result.indent(); + } + result.pr(dest + ".set(" + source + ".value)"); + if (isBank) { + result.pr("_lf_c += 1"); // Increment the count. + result.unindent(); } - result.append(dest + ".set(" + source + ".value)"); + result.unindent(); return result.toString(); } diff --git a/test/Python/src/modal_models/ModalMultiport.lf b/test/Python/src/modal_models/ModalMultiport.lf new file mode 100644 index 0000000000..38790a7e80 --- /dev/null +++ b/test/Python/src/modal_models/ModalMultiport.lf @@ -0,0 +1,63 @@ +target Python { + timeout: 1 ms +} + +reactor Destination(n_inputs=2) { + input[n_inputs] req + output[n_inputs] rsp + + reaction(req) -> rsp {= + for n in range(self.n_inputs): + if req[n].is_present: + rsp[n].set(req[n].value) + =} +} + +reactor Source(n_ports=2) { + output[n_ports] req + input[n_ports] rsp + timer t(0, 1 ms) + + reaction(t) -> req {= + for n in range(self.n_ports): + req[n].set(n) + =} + + reaction(rsp) {= + for n in range(self.n_ports): + print("Received response: ", rsp[n].value); + if rsp[n].value != n: + sys.stderr.write("ERROR: Expected {:d}\n".format(n)) + exit(1) + =} +} + +reactor Selector(n_ports=2) { + input[n_ports] in_req + output[n_ports] out_rsp + + initial mode DST_1 { + dst1 = new Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + DST_2.set() + =} + } + + mode DST_2 { + dst2 = new Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} diff --git a/test/Python/src/modal_models/ModalMultiportBank.lf b/test/Python/src/modal_models/ModalMultiportBank.lf new file mode 100644 index 0000000000..5521a8d2e3 --- /dev/null +++ b/test/Python/src/modal_models/ModalMultiportBank.lf @@ -0,0 +1,63 @@ +target Python { + timeout: 1 ms +} + +reactor Destination(n_inputs=2) { + input[n_inputs] req + output[n_inputs] rsp + + reaction(req) -> rsp {= + for n in range(self.n_inputs): + if req[n].is_present: + rsp[n].set(req[n].value) + =} +} + +reactor Source(n_ports=4) { + output[n_ports] req + input[n_ports] rsp + timer t(0, 1 ms) + + reaction(t) -> req {= + for n in range(self.n_ports): + req[n].set(n) + =} + + reaction(rsp) {= + for n in range(self.n_ports): + print("Received {:d} response: {:d}".format(n, rsp[n].value)) + if rsp[n].value != n: + sys.stderr.write("ERROR: Expected {:d}\n".format(n)) + exit(1) + =} +} + +reactor Selector(n_ports=4, n_dest=2) { + input[n_ports] in_req + output[n_ports] out_rsp + + initial mode DST_1 { + dst1 = new[n_dest] Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + DST_2.set() + =} + } + + mode DST_2 { + dst2 = new[n_dest] Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From f319a5170931515b916e8f3ef0f7ad840084dcec Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 16:40:38 -0700 Subject: [PATCH 083/136] Better reaction to odd cycle detection error --- .../org/lflang/generator/c/CGenerator.java | 19 +++++++++--- .../generator/python/PythonGenerator.java | 31 ++++++++++--------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 44eaad8c68..dda5c06d89 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -81,8 +81,8 @@ import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; -import org.lflang.lf.Variable; import org.lflang.lf.VarRef; +import org.lflang.lf.Variable; import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.TargetConfig; @@ -410,7 +410,10 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { if (!isOSCompatible()) return; // Incompatible OS and configuration // Perform set up that does not generate code - setUpGeneralParameters(); + if (!setUpGeneralParameters()) { + // Failure. + return; + } FileUtil.createDirectoryIfDoesNotExist(fileConfig.getSrcGenPath().toFile()); FileUtil.createDirectoryIfDoesNotExist(fileConfig.binPath.toFile()); @@ -714,7 +717,8 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); if (term.getCode() != null) width.append(term.getCode().getBody()); - else if (term.getParameter() != null) width.append("self->" + term.getParameter().getName()); + else if (term.getParameter() != null) + width.append("self->" + term.getParameter().getName()); else width.append(term.getWidth()); } result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); @@ -2009,8 +2013,8 @@ protected DockerGenerator getDockerGenerator(LFGeneratorContext context) { // ////////////////////////////////////////// // // Protected methods. - // Perform set up that does not generate code - protected void setUpGeneralParameters() { + // Perform set up that does not generate code. Return false on failure. + protected boolean setUpGeneralParameters() { accommodatePhysicalActionsIfPresent(); CompileDefinitionsProperty.INSTANCE.update( targetConfig, @@ -2020,6 +2024,10 @@ protected void setUpGeneralParameters() { // Create the main reactor instance if there is a main reactor. this.main = ASTUtils.createMainReactorInstance(mainDef, reactors, messageReporter, targetConfig); + if (this.main == null) { + // Something went wrong (causality cycle?). Stop. + return false; + } if (hasModalReactors) { // So that each separate compile knows about modal reactors, do this: CompileDefinitionsProperty.INSTANCE.update(targetConfig, Map.of("MODAL_REACTORS", "TRUE")); @@ -2072,6 +2080,7 @@ protected void setUpGeneralParameters() { } pickCompilePlatform(); } + return true; } protected void handleProtoFiles() { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 658c8e4955..667207f267 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -67,7 +67,6 @@ import org.lflang.target.property.ProtobufsProperty; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; -import org.lflang.util.StringUtil; /** * Generator for Python target. This class generates Python code defining each reactor class given @@ -567,9 +566,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = - sourceContainerRef - + sourceAsPort.getName() - + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + sourceContainerRef + + sourceAsPort.getName() + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); var destContainerRef = ""; var destIndex = "_lf_c"; if (destContainer != null) { @@ -584,9 +583,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } } var dest = - destContainerRef - + destAsPort.getName() - + ((destWidth != null) ? "[" + destIndex + "]" : ""); + destContainerRef + + destAsPort.getName() + + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new CodeBuilder(); // If either side is a bank (only one side should be), iterate over it. if (isBank) { @@ -605,9 +604,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // Note that one side could be a multiport of width 1 and the other an ordinary port. if (sourceWidth != null || destWidth != null) { var width = - (sourceAsPort.getWidthSpec() != null) - ? sourceContainerRef + sourceAsPort.getName() - : destContainerRef + destAsPort.getName(); + (sourceAsPort.getWidthSpec() != null) + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); result.pr("for _lf_i in range(" + width + ".width):"); result.indent(); } @@ -621,11 +620,15 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } @Override - protected void setUpGeneralParameters() { - super.setUpGeneralParameters(); - if (hasModalReactors) { - targetConfig.compileAdditionalSources.add("lib/modal_models/impl.c"); + protected boolean setUpGeneralParameters() { + boolean result = super.setUpGeneralParameters(); + if (result) { + if (hasModalReactors) { + targetConfig.compileAdditionalSources.add("lib/modal_models/impl.c"); + } + return true; } + return false; } @Override From af38cba0ef6dfec79dce8f01a7943126c3f8b63e Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 16:52:04 -0700 Subject: [PATCH 084/136] unconditionally define variable --- .../java/org/lflang/generator/python/PythonGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 667207f267..f486c64a47 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -588,8 +588,8 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new CodeBuilder(); // If either side is a bank (only one side should be), iterate over it. + result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. if (isBank) { - result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. var width = new StringBuilder(); for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); @@ -611,11 +611,11 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, result.indent(); } result.pr(dest + ".set(" + source + ".value)"); + result.pr("_lf_c += 1"); // Increment the count. + result.unindent(); if (isBank) { - result.pr("_lf_c += 1"); // Increment the count. result.unindent(); } - result.unindent(); return result.toString(); } From ef67922b46127b0a70bf866e3afe21bdfff6a37b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Fri, 11 Oct 2024 10:40:10 -0700 Subject: [PATCH 085/136] Align reactor-c to main --- core/src/main/resources/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index a370377150..184567d3bd 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit a37037715026caceab6a6e62b94fdf52d8509c06 +Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 From d837e8f0c351c253eb2298a98f9178200be262e6 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 11 Oct 2024 14:06:49 -0700 Subject: [PATCH 086/136] fix: concurrent action override --- core/src/main/resources/lib/c/reactor-c | 2 +- .../Python/src/concurrent/ConcurrentAction.lf | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 test/Python/src/concurrent/ConcurrentAction.lf diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 184567d3bd..0031be283f 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 +Subproject commit 0031be283fb3bf1cb6561fe0cb2c9604ecbb0ef1 diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/ConcurrentAction.lf new file mode 100644 index 0000000000..031d71897b --- /dev/null +++ b/test/Python/src/concurrent/ConcurrentAction.lf @@ -0,0 +1,78 @@ +target Python { + coordination: decentralized # logging: debug +} + +preamble {= + from fastapi import FastAPI, Request, HTTPException + from fastapi.middleware.cors import CORSMiddleware + import threading + import uvicorn + import asyncio + import uuid + import requests + import time + import threading +=} + +reactor WebServer(bank_index=0, STA=0) { + state app + state logs + physical action addlog_action + + reaction(startup) -> addlog_action {= + self.logs = [] + self.app = FastAPI() + self.app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + @self.app.post("/log") + async def addlog(request: Request): + log_message = (await request.json())["log"] + print(f"Received log: {log_message}") + if log_message == "99": + print("Stopping FastAPI server") + os._exit(0) + addlog_action.schedule(0, log_message) + return {"status": "success"} + def test(): + time.sleep(2) + def send_log(log_message, port=5000): + url = f"http://127.0.0.1:{port}/log" + log_data = {"log": f"{log_message}"} + + def send_request(): + try: + requests.post(url, json=log_data, timeout=100) # Send request without waiting for response + except Exception as e: + print(f"Error sending log: {e}") + + thread = threading.Thread(target=send_request) + thread.start() + for i in range(100): + send_log(f"{i}", port=5000) + def run_fastapi_app(): + print(f"[WebServer{self.bank_index}] FastAPI server starting") + uvicorn.run(self.app, host="127.0.0.1", port=5000+self.bank_index, log_level="warning") + fastapi_thread = threading.Thread(target=run_fastapi_app) + fastapi_thread.start() + test_thread = threading.Thread(target=test) + test_thread.start() + =} + + reaction(addlog_action) {= + if addlog_action.value in self.logs: + print(f"Duplicate Action: {addlog_action.value}") + raise Exception("Duplicate Action") + else: + print(f"Action: {addlog_action.value}") + self.logs.append(addlog_action.value) + =} +} + +main reactor { + server = new WebServer() +} From 4a95c99eb9331cad086b96dbbd0d9c8de6e97f14 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 11 Oct 2024 14:14:36 -0700 Subject: [PATCH 087/136] fix: install dependency in test --- test/Python/src/concurrent/ConcurrentAction.lf | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/ConcurrentAction.lf index 031d71897b..72897dcc85 100644 --- a/test/Python/src/concurrent/ConcurrentAction.lf +++ b/test/Python/src/concurrent/ConcurrentAction.lf @@ -3,6 +3,7 @@ target Python { } preamble {= + os.system("pip install uvicorn fastapi --user") from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware import threading From a48814af057554c4e02cabd0d197d857cba455f7 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 11 Oct 2024 14:45:15 -0700 Subject: [PATCH 088/136] update test import --- test/Python/src/concurrent/ConcurrentAction.lf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/ConcurrentAction.lf index 72897dcc85..c7f0339bcf 100644 --- a/test/Python/src/concurrent/ConcurrentAction.lf +++ b/test/Python/src/concurrent/ConcurrentAction.lf @@ -3,7 +3,8 @@ target Python { } preamble {= - os.system("pip install uvicorn fastapi --user") + import subprocess + subprocess.run(["pip", "install", "uvicorn", "fastapi", "--user"], check=True) from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware import threading From 8c810de78e59f0a1c4616afc37166ce12cf251a4 Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 11 Oct 2024 15:05:46 -0700 Subject: [PATCH 089/136] update test import --- test/Python/src/concurrent/ConcurrentAction.lf | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/ConcurrentAction.lf index c7f0339bcf..0719bdf4f6 100644 --- a/test/Python/src/concurrent/ConcurrentAction.lf +++ b/test/Python/src/concurrent/ConcurrentAction.lf @@ -5,15 +5,6 @@ target Python { preamble {= import subprocess subprocess.run(["pip", "install", "uvicorn", "fastapi", "--user"], check=True) - from fastapi import FastAPI, Request, HTTPException - from fastapi.middleware.cors import CORSMiddleware - import threading - import uvicorn - import asyncio - import uuid - import requests - import time - import threading =} reactor WebServer(bank_index=0, STA=0) { @@ -22,6 +13,12 @@ reactor WebServer(bank_index=0, STA=0) { physical action addlog_action reaction(startup) -> addlog_action {= + from fastapi import FastAPI, Request, HTTPException + from fastapi.middleware.cors import CORSMiddleware + import uvicorn + import requests + import time + import threading self.logs = [] self.app = FastAPI() self.app.add_middleware( From 4baee5b68c1eb867c2c4714feb8de179f55cac4e Mon Sep 17 00:00:00 2001 From: depetrol Date: Fri, 11 Oct 2024 15:36:23 -0700 Subject: [PATCH 090/136] update test --- .../Python/src/concurrent/ConcurrentAction.lf | 74 +++++-------------- 1 file changed, 20 insertions(+), 54 deletions(-) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/ConcurrentAction.lf index 0719bdf4f6..2663e8c4cc 100644 --- a/test/Python/src/concurrent/ConcurrentAction.lf +++ b/test/Python/src/concurrent/ConcurrentAction.lf @@ -1,65 +1,31 @@ -target Python { - coordination: decentralized # logging: debug -} - -preamble {= - import subprocess - subprocess.run(["pip", "install", "uvicorn", "fastapi", "--user"], check=True) -=} +target Python -reactor WebServer(bank_index=0, STA=0) { - state app +reactor ConcurrentActionTest { state logs physical action addlog_action reaction(startup) -> addlog_action {= - from fastapi import FastAPI, Request, HTTPException - from fastapi.middleware.cors import CORSMiddleware - import uvicorn - import requests + print("Starting WebServer") import time import threading self.logs = [] - self.app = FastAPI() - self.app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], - ) - @self.app.post("/log") - async def addlog(request: Request): - log_message = (await request.json())["log"] - print(f"Received log: {log_message}") - if log_message == "99": - print("Stopping FastAPI server") - os._exit(0) - addlog_action.schedule(0, log_message) - return {"status": "success"} - def test(): - time.sleep(2) - def send_log(log_message, port=5000): - url = f"http://127.0.0.1:{port}/log" - log_data = {"log": f"{log_message}"} - - def send_request(): - try: - requests.post(url, json=log_data, timeout=100) # Send request without waiting for response - except Exception as e: - print(f"Error sending log: {e}") + def testall(): + def test(i): + print(f"Scheduling action {i}") + addlog_action.schedule(0, f"{i}") - thread = threading.Thread(target=send_request) - thread.start() - for i in range(100): - send_log(f"{i}", port=5000) - def run_fastapi_app(): - print(f"[WebServer{self.bank_index}] FastAPI server starting") - uvicorn.run(self.app, host="127.0.0.1", port=5000+self.bank_index, log_level="warning") - fastapi_thread = threading.Thread(target=run_fastapi_app) - fastapi_thread.start() - test_thread = threading.Thread(target=test) - test_thread.start() + threads = [] + for i in range(100): + test_thread = threading.Thread(target=test, args=(i,)) + test_thread.start() + threads.append(test_thread) + for thread in threads: + thread.join() + print("Test complete") + time.sleep(2) + os._exit(0) + testall_thread = threading.Thread(target=testall) + testall_thread.start() =} reaction(addlog_action) {= @@ -73,5 +39,5 @@ reactor WebServer(bank_index=0, STA=0) { } main reactor { - server = new WebServer() + server = new ConcurrentActionTest() } From 836a01410ea48ed2727a58a9f97c99d9800fa536 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 12 Oct 2024 06:02:06 -0700 Subject: [PATCH 091/136] Move federated test to federated directory --- test/Python/src/{ => federated}/LingoFederatedImport.lf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/Python/src/{ => federated}/LingoFederatedImport.lf (100%) diff --git a/test/Python/src/LingoFederatedImport.lf b/test/Python/src/federated/LingoFederatedImport.lf similarity index 100% rename from test/Python/src/LingoFederatedImport.lf rename to test/Python/src/federated/LingoFederatedImport.lf From a98e3a31c235bb2288cc3a45d218cff8659b6e39 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 12 Oct 2024 06:19:55 -0700 Subject: [PATCH 092/136] Temporary fix for Windows limitation --- test/C/src/Mutable.lf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/C/src/Mutable.lf b/test/C/src/Mutable.lf index 575473986f..a2e7fc6aff 100644 --- a/test/C/src/Mutable.lf +++ b/test/C/src/Mutable.lf @@ -11,7 +11,9 @@ reactor S(width: int = 4) { } reactor R(width: int = 4) { - mutable input[width] in: int + // Pathetically, the Windows C compiler doesn't support arrays on the stack with a variable size. + // So we have to give a constant here instead of the parameter width. + mutable input[4] in: int output[width] out: int reaction(in) -> out {= From 63c6ab1f54b4ddeb80ec53c60d257959e56485c7 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 12 Oct 2024 07:05:34 -0700 Subject: [PATCH 093/136] Update width --- test/C/src/Mutable.lf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/C/src/Mutable.lf b/test/C/src/Mutable.lf index a2e7fc6aff..220ff1afbd 100644 --- a/test/C/src/Mutable.lf +++ b/test/C/src/Mutable.lf @@ -13,7 +13,7 @@ reactor S(width: int = 4) { reactor R(width: int = 4) { // Pathetically, the Windows C compiler doesn't support arrays on the stack with a variable size. // So we have to give a constant here instead of the parameter width. - mutable input[4] in: int + mutable input[2] in: int output[width] out: int reaction(in) -> out {= From 924b3a0acf510267f1f960cd85729779910c79ee Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sat, 12 Oct 2024 14:04:11 -0700 Subject: [PATCH 094/136] Attempted fix for path issue --- core/src/main/java/org/lflang/util/ImportUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/util/ImportUtil.java b/core/src/main/java/org/lflang/util/ImportUtil.java index b7de0a16d4..432f70574b 100644 --- a/core/src/main/java/org/lflang/util/ImportUtil.java +++ b/core/src/main/java/org/lflang/util/ImportUtil.java @@ -25,8 +25,8 @@ public class ImportUtil { * names. */ public static String buildPackageURI(String uriStr, Resource resource) { - Path rootPath = Paths.get(resource.getURI().toString()).toAbsolutePath(); + Path rootPath = FileUtil.toPath(resource); Path uriPath = Paths.get(uriStr.trim()); if (uriPath.getNameCount() < 2) { From ee1be0c6b0cec80e9c7625e808bfd9b5cf12b861 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sat, 12 Oct 2024 15:46:10 -0700 Subject: [PATCH 095/136] Default reactor-ts set to latest release on NPM, not GitHub master --- core/src/main/resources/lib/ts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/ts/package.json b/core/src/main/resources/lib/ts/package.json index fc063d791e..f77ff84e31 100644 --- a/core/src/main/resources/lib/ts/package.json +++ b/core/src/main/resources/lib/ts/package.json @@ -2,7 +2,7 @@ "name": "LinguaFrancaDefault", "type": "commonjs", "dependencies": { - "@lf-lang/reactor-ts": "git://github.com/lf-lang/reactor-ts.git#master", + "@lf-lang/reactor-ts": "^0.6.1", "command-line-args": "^5.1.1", "command-line-usage": "^6.1.3" }, From 04ad5a7277ff0d5962b2bd133a4670c86c797b3c Mon Sep 17 00:00:00 2001 From: vinzbarbuto Date: Sat, 12 Oct 2024 16:07:41 -0700 Subject: [PATCH 096/136] Removed redundant test --- .../src/federated/LingoFederatedImport.lf | 1 - .../FederatedTestImportPackages.lf | 21 ------------------- 2 files changed, 22 deletions(-) delete mode 100644 test/Python/src/lingo_imports/FederatedTestImportPackages.lf diff --git a/test/Python/src/federated/LingoFederatedImport.lf b/test/Python/src/federated/LingoFederatedImport.lf index 5b3a4fadd6..6c642bae6f 100644 --- a/test/Python/src/federated/LingoFederatedImport.lf +++ b/test/Python/src/federated/LingoFederatedImport.lf @@ -1,5 +1,4 @@ # Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets -# Version 1: The LF file is located in "src". target Python { timeout: 2 sec } diff --git a/test/Python/src/lingo_imports/FederatedTestImportPackages.lf b/test/Python/src/lingo_imports/FederatedTestImportPackages.lf deleted file mode 100644 index 4081aa29ba..0000000000 --- a/test/Python/src/lingo_imports/FederatedTestImportPackages.lf +++ /dev/null @@ -1,21 +0,0 @@ -# Test the new import statement for Lingo downloaded packages with the import path enclosed in angle brackets -# Version 2: The LF file is now located in a subdirectory under "src". -target Python { - timeout: 2 sec -} - -import Count from - -reactor Actuator { - input results - - reaction(results) {= - print(f"Count: {results.value}") - =} -} - -federated reactor { - count = new Count() - act = new Actuator() - count.out -> act.results -} From bb350dce53d4331d1cde2cbdc0787d52f4b569a6 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 13 Oct 2024 14:42:23 -0700 Subject: [PATCH 097/136] Workaround for antique Windows C compiler --- test/C/src/token/MutableToken.lf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/C/src/token/MutableToken.lf b/test/C/src/token/MutableToken.lf index 724b8a6579..33d86be4b0 100644 --- a/test/C/src/token/MutableToken.lf +++ b/test/C/src/token/MutableToken.lf @@ -10,7 +10,9 @@ preamble {= =} reactor R(width: int = 4) { - mutable input[width] in: int_array_t* + // Pathetically, the Windows C compiler doesn't support arrays on the stack with a variable size. + // So we have to give a constant here instead of the parameter width. + mutable input[2] in: int_array_t* output[width] out: int_array_t* reaction(in) -> out {= From dfa39901682c9e9684d6f250d50e10bc1a116447 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 13 Oct 2024 17:42:55 -0700 Subject: [PATCH 098/136] Avoid NPE --- core/src/main/java/org/lflang/ast/ASTUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 7e55e3cabc..ef66d24cd1 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -623,7 +623,7 @@ public static ReactorInstance createMainReactorInstance( messageReporter .nowhere() .error("Main reactor has causality cycles. Skipping code generation."); - return null; + return main; // Avoid NPE. } // Inform the run-time of the breadth/parallelism of the reaction graph var breadth = reactionInstanceGraph.getBreadth(); From 3da4aae28120bb2c96425fd283044e39637d3832 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sun, 13 Oct 2024 23:48:39 -0700 Subject: [PATCH 099/136] Attempt to fix Windows/TypeScript issue --- .github/workflows/ts-tests.yml | 4 ++-- core/src/main/resources/lib/ts/package.json | 13 ++++++------- core/src/main/resources/lib/ts/tsconfig.json | 1 - 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ts-tests.yml b/.github/workflows/ts-tests.yml index 79d2e895d3..5e110e9253 100644 --- a/.github/workflows/ts-tests.yml +++ b/.github/workflows/ts-tests.yml @@ -24,9 +24,9 @@ jobs: - name: Prepare build environment uses: ./.github/actions/prepare-build-env - name: Setup Node.js environment - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 - name: Install pnpm run: npm i -g pnpm - name: Install coreutils (macOS) diff --git a/core/src/main/resources/lib/ts/package.json b/core/src/main/resources/lib/ts/package.json index fc063d791e..eec471ab6d 100644 --- a/core/src/main/resources/lib/ts/package.json +++ b/core/src/main/resources/lib/ts/package.json @@ -2,7 +2,7 @@ "name": "LinguaFrancaDefault", "type": "commonjs", "dependencies": { - "@lf-lang/reactor-ts": "git://github.com/lf-lang/reactor-ts.git#master", + "@lf-lang/reactor-ts": "^0.6.1", "command-line-args": "^5.1.1", "command-line-usage": "^6.1.3" }, @@ -11,13 +11,12 @@ "@types/command-line-usage": "^5.0.2", "@types/google-protobuf": "^3.7.4", "@types/microtime": "^2.1.0", - "@types/node": "^18.14.2", - "@typescript-eslint/eslint-plugin": "5.33.0", - "@typescript-eslint/parser": "^5.8.1", - "eslint": "^8.5.0", - "typescript": "~4.8.2", + "@types/node": "^22.5.0", + "eslint-config-prettier": "^9.0.0", + "eslint-config-standard-with-typescript": "^43.0.1", + "typescript": "^5.1.6", "ts-protoc-gen": "^0.15.0", - "rimraf": "^3.0.2" + "rimraf": "^6.0.1" }, "scripts": { "build": "npx rimraf dist && npx tsc --outDir dist" diff --git a/core/src/main/resources/lib/ts/tsconfig.json b/core/src/main/resources/lib/ts/tsconfig.json index ae7bb7804a..bd1f323b67 100644 --- a/core/src/main/resources/lib/ts/tsconfig.json +++ b/core/src/main/resources/lib/ts/tsconfig.json @@ -4,7 +4,6 @@ "target": "esnext", "module": "CommonJS", "types": ["node", "@lf-lang/reactor-ts", "microtime", "command-line-args", "command-line-usage"], - "typeRoots": ["./node_modules/@types/", "./node_modules/@lf-lang/reactor-ts/src/core/@types/"], "esModuleInterop": true, "isolatedModules": true, "lib": ["esnext", "dom"], From 00e9a60fc59cd2b818f303d23f3738cea241dc19 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Wed, 16 Oct 2024 00:04:23 -0700 Subject: [PATCH 100/136] Do not try to run bash script on Windows --- core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt b/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt index e04040f9b3..fdc3388c09 100644 --- a/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt +++ b/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt @@ -53,4 +53,9 @@ class TSFileConfig( super.doClean() FileUtil.deleteDirectory(srcGenPath) } + + override fun getCommand(): LFCommand { + val jsPath = srcGenPath.resolve("dist").resolve("${name}.js") + return LFCommand.get("node", mutableListOf(jsPath.toString()), true, srcPkgPath); + } } From 27c3cd1fdda18d9c5fde6aa40a16a47900f837ed Mon Sep 17 00:00:00 2001 From: depetrol Date: Wed, 16 Oct 2024 11:26:57 -0700 Subject: [PATCH 101/136] fix typescript run script name in windows --- .../src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt | 6 +++--- core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt b/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt index fdc3388c09..5b5820e045 100644 --- a/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt +++ b/core/src/main/kotlin/org/lflang/generator/ts/TSFileConfig.kt @@ -27,6 +27,7 @@ package org.lflang.generator.ts import org.eclipse.emf.ecore.resource.Resource import org.lflang.FileConfig +import org.lflang.generator.GeneratorUtils import org.lflang.util.FileUtil import org.lflang.util.LFCommand import java.io.IOException @@ -54,8 +55,7 @@ class TSFileConfig( FileUtil.deleteDirectory(srcGenPath) } - override fun getCommand(): LFCommand { - val jsPath = srcGenPath.resolve("dist").resolve("${name}.js") - return LFCommand.get("node", mutableListOf(jsPath.toString()), true, srcPkgPath); + override fun getExecutableExtension(): String { + return if (GeneratorUtils.isHostWindows()) ".bat" else "" } } diff --git a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt index 91db8810e1..c4cb4c7fdd 100644 --- a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt @@ -451,7 +451,11 @@ class TSGenerator( context.unsuccessfulFinish() } else { context.finish(GeneratorResult.Status.COMPILED, codeMaps) - val shScriptPath = fileConfig.binPath.resolve(fileConfig.name) + val shScriptPath = if (GeneratorUtils.isHostWindows()) { + fileConfig.binPath.resolve("${fileConfig.name}.bat") + } else { + fileConfig.binPath.resolve(fileConfig.name) + } val jsPath = fileConfig.srcGenPath.resolve("dist").resolve("${fileConfig.name}.js") FileUtil.writeToFile("#!/bin/sh\nnode $jsPath", shScriptPath) shScriptPath.toFile().setExecutable(true) From 279d92e5b393490a8625ea6edf0529b234dc08c1 Mon Sep 17 00:00:00 2001 From: depetrol Date: Wed, 16 Oct 2024 14:18:49 -0700 Subject: [PATCH 102/136] simplify shScriptPath logic --- .../src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt index c4cb4c7fdd..483563de4c 100644 --- a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt @@ -47,6 +47,7 @@ import org.lflang.util.FileUtil import java.nio.file.Files import java.nio.file.Path import java.util.* +import kotlin.io.path.extension private const val NO_NPM_MESSAGE = "The TypeScript target requires npm >= 6.14.4. " + "For installation instructions, see: https://www.npmjs.com/get-npm. \n" + @@ -451,11 +452,7 @@ class TSGenerator( context.unsuccessfulFinish() } else { context.finish(GeneratorResult.Status.COMPILED, codeMaps) - val shScriptPath = if (GeneratorUtils.isHostWindows()) { - fileConfig.binPath.resolve("${fileConfig.name}.bat") - } else { - fileConfig.binPath.resolve(fileConfig.name) - } + val shScriptPath = fileConfig.executable val jsPath = fileConfig.srcGenPath.resolve("dist").resolve("${fileConfig.name}.js") FileUtil.writeToFile("#!/bin/sh\nnode $jsPath", shScriptPath) shScriptPath.toFile().setExecutable(true) From 54612a25dcf3736abad421fe5ca0e5663a504ba8 Mon Sep 17 00:00:00 2001 From: Shulu Li <65802727+Depetrol@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:41:10 -0700 Subject: [PATCH 103/136] Remove unused import Co-authored-by: Marten Lohstroh --- core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt index 483563de4c..c3bb156d97 100644 --- a/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/ts/TSGenerator.kt @@ -47,7 +47,6 @@ import org.lflang.util.FileUtil import java.nio.file.Files import java.nio.file.Path import java.util.* -import kotlin.io.path.extension private const val NO_NPM_MESSAGE = "The TypeScript target requires npm >= 6.14.4. " + "For installation instructions, see: https://www.npmjs.com/get-npm. \n" + From 9aea6792941b97f510af6b9da24a43a2e840f057 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Wed, 16 Oct 2024 15:15:23 -0700 Subject: [PATCH 104/136] Temporarily move test to failing since failure is unrelated to this PR --- test/Python/src/concurrent/{ => failing}/ConcurrentAction.lf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/Python/src/concurrent/{ => failing}/ConcurrentAction.lf (100%) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/failing/ConcurrentAction.lf similarity index 100% rename from test/Python/src/concurrent/ConcurrentAction.lf rename to test/Python/src/concurrent/failing/ConcurrentAction.lf From c2346742e84b32710291c54154df732d25b06840 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Wed, 16 Oct 2024 16:37:34 -0700 Subject: [PATCH 105/136] Do not call Py_FinalizeEx() on failure --- .../org/lflang/generator/python/PythonReactionGenerator.java | 3 +-- core/src/main/resources/lib/c/reactor-c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/python/PythonReactionGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonReactionGenerator.java index 528ec85bf8..d0a1bffac7 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonReactionGenerator.java @@ -118,8 +118,7 @@ private static String generateCPythonFunctionCaller( + " code again", " }", " " + PyUtil.generateGILReleaseCode(), - " Py_FinalizeEx();", - " exit(1);", + " exit(1);", // NOTE: Used to call Py_FinalizeEx() before exit, but it segfaults. "}", "", "/* Release the thread. No Python API allowed beyond this point. */", diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 0031be283f..184567d3bd 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 0031be283fb3bf1cb6561fe0cb2c9604ecbb0ef1 +Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 From 00464bf784e851ee35288982cae3a60430a47cb2 Mon Sep 17 00:00:00 2001 From: depetrol Date: Thu, 17 Oct 2024 15:36:47 -0700 Subject: [PATCH 106/136] fix concurrency and add test --- .../federated/extensions/CExtension.java | 2 +- core/src/main/resources/lib/c/reactor-c | 2 +- .../src/concurrent/ConcurrentActionRepeat.lf | 45 +++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/Python/src/concurrent/ConcurrentActionRepeat.lf diff --git a/core/src/main/java/org/lflang/federated/extensions/CExtension.java b/core/src/main/java/org/lflang/federated/extensions/CExtension.java index 025d20749a..edf5bc8d19 100644 --- a/core/src/main/java/org/lflang/federated/extensions/CExtension.java +++ b/core/src/main/java/org/lflang/federated/extensions/CExtension.java @@ -387,7 +387,7 @@ protected void serializeAndSend( result.pr( "size_t _lf_message_length = " + sendRef - + "->token->length * " + + "->length * " + sendRef + "->token->type->element_size;"); result.pr( diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 184567d3bd..3d7715c39f 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 +Subproject commit 3d7715c39fc40ad3c4c29918e724dc5b96738ca5 diff --git a/test/Python/src/concurrent/ConcurrentActionRepeat.lf b/test/Python/src/concurrent/ConcurrentActionRepeat.lf new file mode 100644 index 0000000000..66c312986f --- /dev/null +++ b/test/Python/src/concurrent/ConcurrentActionRepeat.lf @@ -0,0 +1,45 @@ +target Python + +reactor ConcurrentActionTest { + state logs + physical action addlog_action + + reaction(startup) -> addlog_action {= + print("Starting WebServer") + import time + import threading + self.logs = [] + def testall(): + def test(i): + print(f"Scheduling action {i}") + addlog_action.schedule(0, f"{i}") + + threads = [] + for j in range(100): + self.logs = [] + for i in range(100): + test_thread = threading.Thread(target=test, args=(j*100 + i,)) + test_thread.start() + threads.append(test_thread) + for thread in threads: + thread.join() + time.sleep(0.1) + print(f"===== Test {j} complete =====") + os._exit(0) + testall_thread = threading.Thread(target=testall) + testall_thread.start() + =} + + reaction(addlog_action) {= + if addlog_action.value in self.logs: + print(f"Duplicate Action: {addlog_action.value}") + raise Exception("Duplicate Action") + else: + print(f"Action: {addlog_action.value}") + self.logs.append(addlog_action.value) + =} +} + +main reactor { + server = new ConcurrentActionTest() +} From d6bb04b180efb7cfdefd359fe15423c0bb94c248 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sun, 20 Oct 2024 15:56:15 -0700 Subject: [PATCH 107/136] Update all-misc.yml --- .github/workflows/all-misc.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/all-misc.yml b/.github/workflows/all-misc.yml index 1155170fc1..e2aae3d1ff 100644 --- a/.github/workflows/all-misc.yml +++ b/.github/workflows/all-misc.yml @@ -41,14 +41,6 @@ jobs: with: all-platforms: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} - # Run language server tests. - lsp: - if: ${{ needs.check-diff.outputs.run_misc == 'true' }} - needs: check-diff - uses: ./.github/workflows/lsp-tests.yml - with: - all-platforms: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} - check-labels: uses: ./.github/workflows/check-labels.yml if: ${{ github.event_name == 'pull_request' }} From 9a93cf65fcf65740ace6e37de48216de3cd25370 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sun, 20 Oct 2024 15:58:39 -0700 Subject: [PATCH 108/136] Update lsp-tests.yml --- .github/workflows/lsp-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lsp-tests.yml b/.github/workflows/lsp-tests.yml index 0a50fbf85a..a1568dbcd5 100644 --- a/.github/workflows/lsp-tests.yml +++ b/.github/workflows/lsp-tests.yml @@ -1,6 +1,7 @@ name: Language server tests on: + workflow_dispatch: workflow_call: inputs: all-platforms: From 6175dc468c81cf66ebe313b3f78cec8a4733d24d Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sun, 20 Oct 2024 15:59:56 -0700 Subject: [PATCH 109/136] Update lsp-tests.yml --- .github/workflows/lsp-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/lsp-tests.yml b/.github/workflows/lsp-tests.yml index a1568dbcd5..a724ed42e1 100644 --- a/.github/workflows/lsp-tests.yml +++ b/.github/workflows/lsp-tests.yml @@ -1,6 +1,9 @@ name: Language server tests on: + schedule: + # * is a special character in YAML so you have to quote this string + - cron: '0 8 * * 6' workflow_dispatch: workflow_call: inputs: From f5de81e50116b1bff94ca2416ff14d92796b7853 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 21 Oct 2024 11:45:14 +0200 Subject: [PATCH 110/136] Patmos tests are excluded from cuncurrent and regular-tests --- .../java/org/lflang/tests/RuntimeTest.java | 5 +++-- .../java/org/lflang/tests/runtime/CCppTest.java | 1 + .../java/org/lflang/tests/runtime/CPatmosTest.java | 13 ------------- .../java/org/lflang/tests/TestRegistry.java | 1 + 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/core/src/integrationTest/java/org/lflang/tests/RuntimeTest.java b/core/src/integrationTest/java/org/lflang/tests/RuntimeTest.java index 2f170ec488..e35d45f79f 100644 --- a/core/src/integrationTest/java/org/lflang/tests/RuntimeTest.java +++ b/core/src/integrationTest/java/org/lflang/tests/RuntimeTest.java @@ -232,7 +232,7 @@ public static boolean compatibleWithThreadingOff(TestCategory category) { // CONCURRENT, FEDERATED, DOCKER_FEDERATED, DOCKER // are not compatible with single-threaded execution. - // ARDUINO, ZEPHYR and FLEXPRET have their own test suites, so we don't need to rerun. + // ARDUINO, ZEPHYR, FLEXPRET, and PATMOS have their own test suites, so we don't need to rerun. boolean excluded = category == TestCategory.CONCURRENT || category == TestCategory.SERIALIZATION @@ -245,7 +245,8 @@ public static boolean compatibleWithThreadingOff(TestCategory category) { || category == TestCategory.ZEPHYR_UNTHREADED || category == TestCategory.ZEPHYR_BOARDS || category == TestCategory.ZEPHYR_THREADED - || category == TestCategory.FLEXPRET; + || category == TestCategory.FLEXPRET + || category == TestCategory.PATMOS; // SERIALIZATION and TARGET tests are excluded on Windows. excluded |= isWindows() && category == TestCategory.TARGET; diff --git a/core/src/integrationTest/java/org/lflang/tests/runtime/CCppTest.java b/core/src/integrationTest/java/org/lflang/tests/runtime/CCppTest.java index cd890517f7..687a12011e 100644 --- a/core/src/integrationTest/java/org/lflang/tests/runtime/CCppTest.java +++ b/core/src/integrationTest/java/org/lflang/tests/runtime/CCppTest.java @@ -48,6 +48,7 @@ private static boolean isExcludedFromCCpp(TestCategory category) { excluded |= category == TestCategory.ZEPHYR_THREADED; excluded |= category == TestCategory.ZEPHYR_BOARDS; excluded |= category == TestCategory.ARDUINO; + excluded |= category == TestCategory.PATMOS; excluded |= category == TestCategory.NO_INLINING; excluded |= category == TestCategory.VERIFIER; return !excluded; diff --git a/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java index 3672c15355..293d1fbe5b 100644 --- a/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java +++ b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java @@ -39,19 +39,6 @@ public CPatmosTest() { super(Target.C); } - @Test - public void buildPatmosConcurrent() { - Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); - super.runTestsFor( - List.of(Target.C), - "Build concurrent tests for Patmos.", - TestCategory.CONCURRENT::equals, - Transformers::noChanges, - Configurators::makePatmosCompatible, - TestLevel.BUILD, - false); - } - @Test public void buildPatmosBasicTestsUnthreaded() { Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); diff --git a/core/src/testFixtures/java/org/lflang/tests/TestRegistry.java b/core/src/testFixtures/java/org/lflang/tests/TestRegistry.java index ab20848871..fc74f30d76 100644 --- a/core/src/testFixtures/java/org/lflang/tests/TestRegistry.java +++ b/core/src/testFixtures/java/org/lflang/tests/TestRegistry.java @@ -337,6 +337,7 @@ public enum TestCategory { ZEPHYR_UNTHREADED(false, "zephyr" + File.separator + "unthreaded", TestLevel.BUILD), ZEPHYR_BOARDS(false, "zephyr" + File.separator + "boards", TestLevel.BUILD), FLEXPRET(false, "flexpret", TestLevel.BUILD), + PATMOS(false, "patmos", TestLevel.BUILD), VERIFIER(false, "verifier", TestLevel.EXECUTION), TARGET(false, "", TestLevel.EXECUTION); From 813fb6ac251973d95f2ed521839a3721238a2d79 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 21 Oct 2024 13:35:52 +0200 Subject: [PATCH 111/136] Patmos threaded basic test is removed --- .../java/org/lflang/tests/runtime/CPatmosTest.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java index 293d1fbe5b..8dd7c67e35 100644 --- a/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java +++ b/core/src/integrationTest/java/org/lflang/tests/runtime/CPatmosTest.java @@ -51,17 +51,4 @@ public void buildPatmosBasicTestsUnthreaded() { TestLevel.BUILD, false); } - - @Test - public void buildPatmosBasicTests() { - Assumptions.assumeTrue(isLinux(), "Patmos tests only supported on Linux"); - super.runTestsFor( - List.of(Target.C), - "Build basic tests for Patmos.", - TestCategory.BASIC::equals, - Transformers::noChanges, - Configurators::makePatmosCompatible, - TestLevel.BUILD, - false); - } } From ec47a9161ca62c6691162aabea1214a734387a5d Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Mon, 21 Oct 2024 22:07:55 -0700 Subject: [PATCH 112/136] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5af0226c8d..6ad4e01a6c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [Website](https://lf-lang.org/) | [Documentation](https://www.lf-lang.org/docs/) | -[Download](https://www.lf-lang.org/docs/installation) | +[Installation](https://www.lf-lang.org/docs/installation) | [Contributing](CONTRIBUTING.md) | [Changelog](CHANGELOG.md) @@ -8,7 +8,10 @@ [![CI (misc)](https://github.com/lf-lang/lingua-franca/actions/workflows/all-misc.yml/badge.svg)](https://github.com/lf-lang/lingua-franca/actions/workflows/all-misc.yml?query=branch%3Amaster) [![CI (misc)](https://github.com/lf-lang/lingua-franca/actions/workflows/all-embedded.yml/badge.svg)]([https://github.com/lf-lang/lingua-franca/actions/](https://github.com/lf-lang/lingua-franca/actions/workflows/all-embedded.yml?query=branch%3Amaster)) -[![Nightly Build](https://github.com/lf-lang/lingua-franca/actions/workflows/nightly-build.yml/badge.svg)](https://github.com/lf-lang/lingua-franca/actions/workflows/nightly-build.yml) +[![Open VSX Downloads](https://img.shields.io/open-vsx/dt/lf-lang/vscode-lingua-franca?label=Open%20VSX%20Registry%20%E2%A4%93)](https://open-vsx.org/extension/lf-lang/vscode-lingua-franca) +[![Visual Studio Marketplace Downloads](https://img.shields.io/visual-studio-marketplace/d/lf-lang.vscode-lingua-franca?label=VS%20Marketplace%20%E2%A4%93)](https://marketplace.visualstudio.com/items?itemName=lf-lang.vscode-lingua-franca) +[![Nightly Build](https://github.com/lf-lang/lingua-franca/actions/workflows/nightly-build.yml/badge.svg)](https://github.com/lf-lang/lingua-franca/releases/tag/nightly) + [![CodeCov](https://codecov.io/gh/lf-lang/lingua-franca/branch/master/graph/badge.svg?token=b7LrpihI5a)](https://codecov.io/gh/lf-lang/lingua-franca) [![GitHub Contributors](https://img.shields.io/github/contributors/lf-lang/lingua-franca)](https://github.com/lf-lang/lingua-franca/graphs/contributors) [![Zulip](https://img.shields.io/badge/chat-zulip-informational)](https://lf-lang.zulipchat.com) @@ -19,6 +22,4 @@ Lingua Franca (LF) is a polyglot coordination language for concurrent and possibly time-sensitive applications ranging from low-level embedded code to distributed cloud and edge applications. An LF program specifies the interactions between components called reactors. The emphasis of the framework is on ensuring deterministic interaction with explicit management of timing. The logic of each reactor is written in one of a suite of target languages (currently C, C++, Python, and TypeScript) and can integrate legacy code in those languages. A code generator synthesizes one or more programs in the target language, which are then compiled using standard toolchains. If the application has exploitable parallelism, then it executes transparently on multiple cores without compromising determinacy. A distributed application translates into multiple programs and scripts to launch those programs on distributed machines. The communication fabric connecting components is synthesized as part of the programs. -See [lf-lang.org](https://lf-lang.org) for installation instructions and documentation. See also the [wiki](https://github.com/icyphy/lingua-franca/wiki) for further information on ongoing projects. - -See our [Publications and Presentations](https://www.lf-lang.org/research/). +See [lf-lang.org](https://lf-lang.org) for [installation instructions](https://www.lf-lang.org/docs/installation), [documentation](https://www.lf-lang.org/docs/), and [research papers](https://www.lf-lang.org/research/). See also the [wiki](https://github.com/lf-lang/lingua-franca/wiki/) for further information on ongoing projects. From 46da427b4687d4f485f60de74453300bed617eb7 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 24 Oct 2024 20:40:10 +0200 Subject: [PATCH 113/136] reactor-cpp points to dfdac2c --- core/src/main/resources/lib/cpp/reactor-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/cpp/reactor-cpp b/core/src/main/resources/lib/cpp/reactor-cpp index 65dff1fd22..dfdac2c19e 160000 --- a/core/src/main/resources/lib/cpp/reactor-cpp +++ b/core/src/main/resources/lib/cpp/reactor-cpp @@ -1 +1 @@ -Subproject commit 65dff1fd22d80305473acaf34a7e5209521b5ec0 +Subproject commit dfdac2c19e8d111cf4741c8bf8f304678a59d025 From 1eac55cb6aebfd46733640a0e2600e275443ec99 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Mon, 28 Oct 2024 23:27:31 +0500 Subject: [PATCH 114/136] with latest cpp runtime code --- core/src/main/resources/lib/cpp/reactor-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/cpp/reactor-cpp b/core/src/main/resources/lib/cpp/reactor-cpp index dfdac2c19e..ae09ff11b1 160000 --- a/core/src/main/resources/lib/cpp/reactor-cpp +++ b/core/src/main/resources/lib/cpp/reactor-cpp @@ -1 +1 @@ -Subproject commit dfdac2c19e8d111cf4741c8bf8f304678a59d025 +Subproject commit ae09ff11b131ff926bc4af3b4b4b466c6ca16c1d From c1d483718c3376c7f9c34c28e2052a27d5df550c Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Tue, 29 Oct 2024 01:18:44 +0500 Subject: [PATCH 115/136] fqn function exposed to LFScope --- core/src/main/resources/lib/cpp/lfutil.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/resources/lib/cpp/lfutil.hh b/core/src/main/resources/lib/cpp/lfutil.hh index ef7880f301..c74e9603a2 100644 --- a/core/src/main/resources/lib/cpp/lfutil.hh +++ b/core/src/main/resources/lib/cpp/lfutil.hh @@ -60,6 +60,7 @@ public: reactor::Duration get_elapsed_logical_time() const { return reactor->get_elapsed_logical_time(); } reactor::Duration get_elapsed_physical_time() const { return reactor->get_elapsed_physical_time(); } reactor::Environment* environment() const { return reactor->environment(); } + const std::string& fqn() const { return reactor->fqn(); } void request_stop() const { return environment()->sync_shutdown(); } }; From c7dd5c8ab62313461c68c291950cf6a1502dad35 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Wed, 30 Oct 2024 01:07:14 +0500 Subject: [PATCH 116/136] test file added for FQN validation --- test/Cpp/src/FqnTest.lf | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 test/Cpp/src/FqnTest.lf diff --git a/test/Cpp/src/FqnTest.lf b/test/Cpp/src/FqnTest.lf new file mode 100644 index 0000000000..0635afe9ce --- /dev/null +++ b/test/Cpp/src/FqnTest.lf @@ -0,0 +1,51 @@ +target Cpp { + workers: 1 +} + +reactor A (bank_index:size_t = 0) { + reaction (startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction (shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} +} + +reactor B (bank_index:size_t = 0) { + a = new [3] A(); + reaction (startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction (shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} +} + +reactor C (bank_index:size_t = 0) { + b = new [2] B(); + reaction (startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction (shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} +} + +reactor D (bank_index:size_t = 0) { + a = new [2] A(); + reaction (startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction (shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} +} + +main reactor { + c = new [2] C(); + d = new [3] D(); +} \ No newline at end of file From 8f2366e49714cb1df306115146b32130713e6895 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Wed, 30 Oct 2024 13:47:26 +0500 Subject: [PATCH 117/136] formatting changes to test file --- test/Cpp/src/FqnTest.lf | 73 +++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/test/Cpp/src/FqnTest.lf b/test/Cpp/src/FqnTest.lf index 0635afe9ce..aa85072c55 100644 --- a/test/Cpp/src/FqnTest.lf +++ b/test/Cpp/src/FqnTest.lf @@ -1,51 +1,54 @@ target Cpp { - workers: 1 + workers: 1 } -reactor A (bank_index:size_t = 0) { - reaction (startup) {= - std::cout << fqn() << " Started\n"; - =} +reactor A(bank_index: size_t = 0) { + reaction(startup) {= + std::cout << fqn() << " Started\n"; + =} - reaction (shutdown) {= - std::cout << fqn() << " Terminated\n"; - =} + reaction(shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} } -reactor B (bank_index:size_t = 0) { - a = new [3] A(); - reaction (startup) {= - std::cout << fqn() << " Started\n"; - =} +reactor B(bank_index: size_t = 0) { + a = new[3] A() - reaction (shutdown) {= - std::cout << fqn() << " Terminated\n"; - =} + reaction(startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction(shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} } -reactor C (bank_index:size_t = 0) { - b = new [2] B(); - reaction (startup) {= - std::cout << fqn() << " Started\n"; - =} +reactor C(bank_index: size_t = 0) { + b = new[2] B() + + reaction(startup) {= + std::cout << fqn() << " Started\n"; + =} - reaction (shutdown) {= - std::cout << fqn() << " Terminated\n"; - =} + reaction(shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} } -reactor D (bank_index:size_t = 0) { - a = new [2] A(); - reaction (startup) {= - std::cout << fqn() << " Started\n"; - =} +reactor D(bank_index: size_t = 0) { + a = new[2] A() - reaction (shutdown) {= - std::cout << fqn() << " Terminated\n"; - =} + reaction(startup) {= + std::cout << fqn() << " Started\n"; + =} + + reaction(shutdown) {= + std::cout << fqn() << " Terminated\n"; + =} } main reactor { - c = new [2] C(); - d = new [3] D(); -} \ No newline at end of file + c = new[2] C() + d = new[3] D() +} From 1633b41ed8690d8f062951ca8929adf7d3197284 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Wed, 30 Oct 2024 14:17:20 +0500 Subject: [PATCH 118/136] add name() support inside reactions, validation of name against fqn in test file --- core/src/main/resources/lib/cpp/lfutil.hh | 1 + test/Cpp/src/FqnTest.lf | 36 ++++++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/core/src/main/resources/lib/cpp/lfutil.hh b/core/src/main/resources/lib/cpp/lfutil.hh index c74e9603a2..aa09e0f0f9 100644 --- a/core/src/main/resources/lib/cpp/lfutil.hh +++ b/core/src/main/resources/lib/cpp/lfutil.hh @@ -61,6 +61,7 @@ public: reactor::Duration get_elapsed_physical_time() const { return reactor->get_elapsed_physical_time(); } reactor::Environment* environment() const { return reactor->environment(); } const std::string& fqn() const { return reactor->fqn(); } + const std::string& name() const { return reactor->name(); } void request_stop() const { return environment()->sync_shutdown(); } }; diff --git a/test/Cpp/src/FqnTest.lf b/test/Cpp/src/FqnTest.lf index aa85072c55..5eec85bb13 100644 --- a/test/Cpp/src/FqnTest.lf +++ b/test/Cpp/src/FqnTest.lf @@ -2,13 +2,21 @@ target Cpp { workers: 1 } +public preamble {= + inline bool name_validation (const std::string& fqn, const std::string& name) { + size_t last_dot = fqn.find_last_of('.'); + return (last_dot == std::string::npos) ? (name == fqn) : (name == fqn.substr(last_dot + 1)); + } +=} + reactor A(bank_index: size_t = 0) { reaction(startup) {= - std::cout << fqn() << " Started\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Started\n"; + assert (name_validation(fqn(), name())); =} reaction(shutdown) {= - std::cout << fqn() << " Terminated\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Terminated\n"; =} } @@ -16,11 +24,12 @@ reactor B(bank_index: size_t = 0) { a = new[3] A() reaction(startup) {= - std::cout << fqn() << " Started\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Started\n"; + assert (name_validation(fqn(), name())); =} reaction(shutdown) {= - std::cout << fqn() << " Terminated\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Terminated\n"; =} } @@ -28,11 +37,12 @@ reactor C(bank_index: size_t = 0) { b = new[2] B() reaction(startup) {= - std::cout << fqn() << " Started\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Started\n"; + assert (name_validation(fqn(), name())); =} reaction(shutdown) {= - std::cout << fqn() << " Terminated\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Terminated\n"; =} } @@ -40,15 +50,25 @@ reactor D(bank_index: size_t = 0) { a = new[2] A() reaction(startup) {= - std::cout << fqn() << " Started\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Started\n"; + assert (name_validation(fqn(), name())); =} reaction(shutdown) {= - std::cout << fqn() << " Terminated\n"; + std::cout << "fqn:" << fqn() << " name:" << name() << " Terminated\n"; =} } main reactor { c = new[2] C() d = new[3] D() + + reaction(startup) {= + std::cout << "fqn:" << fqn() << " name:" << name() << " Started\n"; + assert (name_validation(fqn(), name())); + =} + + reaction(shutdown) {= + std::cout << "fqn:" << fqn() << " name:" << name() << " Terminated\n"; + =} } From 8805037e6be425b1479db8d7d4f662d40eab27b0 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Wed, 30 Oct 2024 14:59:21 +0500 Subject: [PATCH 119/136] add validations for empty name and fqn, to make sure this kind of bug doesn't fall through the cracks --- test/Cpp/src/FqnTest.lf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Cpp/src/FqnTest.lf b/test/Cpp/src/FqnTest.lf index 5eec85bb13..3be6999fe1 100644 --- a/test/Cpp/src/FqnTest.lf +++ b/test/Cpp/src/FqnTest.lf @@ -4,6 +4,9 @@ target Cpp { public preamble {= inline bool name_validation (const std::string& fqn, const std::string& name) { + if (fqn.empty() || name.empty()) { + return false; + } size_t last_dot = fqn.find_last_of('.'); return (last_dot == std::string::npos) ? (name == fqn) : (name == fqn.substr(last_dot + 1)); } From cf35e320a7aec3309d5ca4c6d63551d7f0049b49 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Thu, 31 Oct 2024 18:40:29 +0100 Subject: [PATCH 120/136] bumping reactor-cpp version --- core/src/main/resources/lib/cpp/reactor-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/cpp/reactor-cpp b/core/src/main/resources/lib/cpp/reactor-cpp index ae09ff11b1..df03ee5fd5 160000 --- a/core/src/main/resources/lib/cpp/reactor-cpp +++ b/core/src/main/resources/lib/cpp/reactor-cpp @@ -1 +1 @@ -Subproject commit ae09ff11b131ff926bc4af3b4b4b466c6ca16c1d +Subproject commit df03ee5fd5f04c0e20aa41886e914ff5d674805c From d8c12f9138406d8fd8a12856cbb454f91c6c090c Mon Sep 17 00:00:00 2001 From: tanneberger Date: Thu, 31 Oct 2024 18:50:28 +0100 Subject: [PATCH 121/136] bumping version --- core/src/main/resources/lib/cpp/reactor-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/lib/cpp/reactor-cpp b/core/src/main/resources/lib/cpp/reactor-cpp index df03ee5fd5..e0df4349bb 160000 --- a/core/src/main/resources/lib/cpp/reactor-cpp +++ b/core/src/main/resources/lib/cpp/reactor-cpp @@ -1 +1 @@ -Subproject commit df03ee5fd5f04c0e20aa41886e914ff5d674805c +Subproject commit e0df4349bb5726e659d5c6589fa948a18991e2b8 From 4e88313bae34487902b6416294e9630d9f3e2b9e Mon Sep 17 00:00:00 2001 From: "lingua-franca[bot]" <97201490+francabot@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:28:32 -0700 Subject: [PATCH 122/136] Update CHANGELOG.md --- CHANGELOG.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 797482fbeb..fdcec281d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,77 @@ # Changelog + +## [v0.9.0](https://github.com/lf-lang/lingua-franca/tree/v0.9.0) (2024-10-31) + +**Highlights** + +This release of Lingua Franca adds support for reusable and publishable packages, providing the necessary infrastructure to develop a community-driven ecosystem of Lingua Franca packages. The VS code extension now features an integrated package explorer, and the diagrams provide colored highlighting for selected diagram edges. Other new features include C support for a new hardware platform called Patmos, several minor syntax and API improvements, and a new Alpine-based default Docker image for Python. This release also includes numerous bug fixes, such as preventing hangs during timeouts, addressing issues in decentralized coordination, improving error handling, and fixing concurrency issues in the C runtime. + +**🚀 New Features** + +- Colored highlighting of selected diagram edges [\#2324](https://github.com/lf-lang/lingua-franca/pull/2324) (@soerendomroes) +- Native `forever` and `never` time literal [\#2421](https://github.com/lf-lang/lingua-franca/pull/2421) (@Depetrol) +- Angular bracket imports for reusable reactor modules [\#2404](https://github.com/lf-lang/lingua-franca/pull/2404) (@vinzbarbuto) +- Support for Patmos platform [\#2383](https://github.com/lf-lang/lingua-franca/pull/2383) (@EhsanKhodadad) +- API for getting fully-qualified name in Cpp target [\#2431](https://github.com/lf-lang/lingua-franca/pull/2431) (@OmerMajNition) + +**✨ Enhancements** + +- Changes in the Lingua Franca Language Server to support improvements in the VSCode extension [\#2370](https://github.com/lf-lang/lingua-franca/pull/2370) (@vinzbarbuto) +- Default Docker image for Python changed to Alpine [\#2413](https://github.com/lf-lang/lingua-franca/pull/2413) (@lhstrh) +- Modal multiport [\#2422](https://github.com/lf-lang/lingua-franca/pull/2422) (@edwardalee) + +**🔧 Fixes** + +- Improvements in decentralized coordination [\#2394](https://github.com/lf-lang/lingua-franca/pull/2394) (@edwardalee) +- Prevent hanging on waiting for timeout time [\#2399](https://github.com/lf-lang/lingua-franca/pull/2399) (@edwardalee) +- Fix bank_index Parameter Override [\#2411](https://github.com/lf-lang/lingua-franca/pull/2411) (@Depetrol) +- Fix action is_present field not being reset [\#2409](https://github.com/lf-lang/lingua-franca/pull/2409) (@erlingrj) +- Informative error message for platforms that do not support federated [\#2414](https://github.com/lf-lang/lingua-franca/pull/2414) (@lhstrh) +- Corrected behavior of federated code generation under `--no-compile` flag [\#2415](https://github.com/lf-lang/lingua-franca/pull/2415) (@lhstrh) +- Fix disconnected port handling [\#2416](https://github.com/lf-lang/lingua-franca/pull/2416) (@edwardalee) +- Fixed parameterized mutable inputs [\#2420](https://github.com/lf-lang/lingua-franca/pull/2420) (@edwardalee) +- Fixed concurrency bug in action scheduling in C runtime [\#2423](https://github.com/lf-lang/lingua-franca/pull/2423) (@Depetrol) +- Fix windows [\#2424](https://github.com/lf-lang/lingua-franca/pull/2424) (@edwardalee) +- File extension of TypeScript launch script adjusted on Windows [\#2427](https://github.com/lf-lang/lingua-franca/pull/2427) (@petervdonovan) +- Modal multiport [\#2422](https://github.com/lf-lang/lingua-franca/pull/2422) (@edwardalee) +- No segfault when Python reactions fail [\#2428](https://github.com/lf-lang/lingua-franca/pull/2428) (@edwardalee) +- Fixed concurrency another bug in action scheduling in C runtime [\#2429](https://github.com/lf-lang/lingua-franca/pull/2429) (@Depetrol) + + +### Submodule [lf-lang/reactor-c](http://github.com/lf-lang/reactor-c) + +**🚀 New Features** + +- lf_sleep and lf_nanosleep added to lf_patmos_support [\#478](https://github.com/lf-lang/reactor-c/pull/478) (@EhsanKhodadad) + +**✨ Enhancements** + +- Prevent hanging on waiting for timeout time [\#477](https://github.com/lf-lang/reactor-c/pull/477) (@edwardalee) + +**🔧 Fixes** + +- Bugfixes in decentralized coordination [\#476](https://github.com/lf-lang/reactor-c/pull/476) (@edwardalee) +- Fix action is_present field not being reset [\#482](https://github.com/lf-lang/reactor-c/pull/482) (@erlingrj) +- Prevent a warning when the second timer event is after the timeout time. [\#487](https://github.com/lf-lang/reactor-c/pull/487) (@edwardalee) +- Fix Unintended Action Override [\#490](https://github.com/lf-lang/reactor-c/pull/490) (@Depetrol) +- Fix Unintended Action Override [\#491](https://github.com/lf-lang/reactor-c/pull/491) (@Depetrol) + +**🚧 Maintenance and Refactoring** + +- Fix compiler warnings in Zephyr and FlexPRET support files [\#479](https://github.com/lf-lang/reactor-c/pull/479) (@erlingrj) +- Improved formatting in Dockerfile [\#483](https://github.com/lf-lang/reactor-c/pull/483) (@lhstrh) +- Various fixes to silence warnings on Windows [\#486](https://github.com/lf-lang/reactor-c/pull/486) (@edwardalee) + + +### Submodule [lf-lang/reactor-cpp](http://github.com/lf-lang/reactor-cpp) + +- Fix clang-tidy configuration and tidy up code [\#60](https://github.com/lf-lang/reactor-cpp/pull/60) (@cmnrd) + +### Submodule [lf-lang/reactor-rs](http://github.com/lf-lang/reactor-rs) + +- No Changes + + ## [v0.8.2](https://github.com/lf-lang/lingua-franca/tree/v0.8.2) (2024-08-02) From b5dce6e285fd701ac61f7400bdfb0005bdbafb5e Mon Sep 17 00:00:00 2001 From: "lingua-franca[bot]" <97201490+francabot@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:31:24 -0700 Subject: [PATCH 123/136] Bump version to 0.9.0 --- CHANGELOG.md | 2 +- core/src/main/resources/org/lflang/StringsBundle.properties | 2 +- gradle.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdcec281d7..00522f3201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Changelog - + ## [v0.9.0](https://github.com/lf-lang/lingua-franca/tree/v0.9.0) (2024-10-31) **Highlights** diff --git a/core/src/main/resources/org/lflang/StringsBundle.properties b/core/src/main/resources/org/lflang/StringsBundle.properties index e0689f1107..b815a26bf8 100644 --- a/core/src/main/resources/org/lflang/StringsBundle.properties +++ b/core/src/main/resources/org/lflang/StringsBundle.properties @@ -1 +1 @@ -VERSION = 0.8.3-SNAPSHOT +VERSION = 0.9.0 diff --git a/gradle.properties b/gradle.properties index 8220073f54..530886f9f2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ [header] group=org.lflang -version=0.8.3-SNAPSHOT +version=0.9.0 [versions] antlrVersion=4.7.2 From 508f49c098caf67ebcbcb8c8f82ee084c7b92b81 Mon Sep 17 00:00:00 2001 From: "lingua-franca[bot]" <97201490+francabot@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:08:05 -0700 Subject: [PATCH 124/136] Bump version to 0.9.1-SNAPSHOT --- core/src/main/resources/org/lflang/StringsBundle.properties | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/org/lflang/StringsBundle.properties b/core/src/main/resources/org/lflang/StringsBundle.properties index b815a26bf8..732ea8b8fb 100644 --- a/core/src/main/resources/org/lflang/StringsBundle.properties +++ b/core/src/main/resources/org/lflang/StringsBundle.properties @@ -1 +1 @@ -VERSION = 0.9.0 +VERSION = 0.9.1-SNAPSHOT diff --git a/gradle.properties b/gradle.properties index 530886f9f2..b844c48ff6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ [header] group=org.lflang -version=0.9.0 +version=0.9.1-SNAPSHOT [versions] antlrVersion=4.7.2 From 2e6d57fa801f9fa4a51d30e3d71bf7c825e5dee9 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 9 Nov 2024 07:52:34 -0800 Subject: [PATCH 125/136] Define TPO in comments --- .../java/org/lflang/generator/ReactionInstanceGraph.java | 6 +++++- .../src/main/java/org/lflang/generator/ReactorInstance.java | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/ReactionInstanceGraph.java b/core/src/main/java/org/lflang/generator/ReactionInstanceGraph.java index 5ce3ff38fb..ceb2404538 100644 --- a/core/src/main/java/org/lflang/generator/ReactionInstanceGraph.java +++ b/core/src/main/java/org/lflang/generator/ReactionInstanceGraph.java @@ -223,7 +223,11 @@ protected void addNodesAndEdges(ReactorInstance reactor) { registerPortInstances(reactor); } - /** Add edges that encode the precedence relations induced by the TPO levels. */ + /** + * Add edges that encode the precedence relations induced by the TPO levels. TPO is total port + * order. See + * https://github.com/icyphy/lf-pubs/blob/54af48a97cc95058dbfb3333b427efb70294f66c/federated/TOMACS/paper.tex#L1353 + */ private void addEdgesForTpoLevels(ReactorInstance main) { var constrainedReactions = getConstrainedReactions(main); for (var i : constrainedReactions.keySet()) { diff --git a/core/src/main/java/org/lflang/generator/ReactorInstance.java b/core/src/main/java/org/lflang/generator/ReactorInstance.java index 39f7cd03da..db4b301d2d 100644 --- a/core/src/main/java/org/lflang/generator/ReactorInstance.java +++ b/core/src/main/java/org/lflang/generator/ReactorInstance.java @@ -181,7 +181,8 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, MessageReporter /** * The TPO level with which {@code this} was annotated, or {@code null} if there is no TPO - * annotation. + * annotation. TPO is total port order. See + * https://github.com/icyphy/lf-pubs/blob/54af48a97cc95058dbfb3333b427efb70294f66c/federated/TOMACS/paper.tex#L1353 */ public final Integer tpoLevel; From b7dac8b09e7618ec289393864ffba2dc7576abfc Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 14 Nov 2024 14:11:18 +0100 Subject: [PATCH 126/136] bug fix in patmos platform --- core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java index 5931399052..152435bca9 100644 --- a/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CCmakeGenerator.java @@ -233,6 +233,8 @@ CodeBuilder generateCMakeCode( "find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\")"); cMakeCode.pr("set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE})"); + cMakeCode.pr( + "set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\")"); // patmos-clang cannot compiler -O3 cMakeCode.pr("project(" + executableName + " LANGUAGES C)"); cMakeCode.newLine(); break; From 048fb80aef21726c2ee26180d8f4589a8b0ebd96 Mon Sep 17 00:00:00 2001 From: Christian Menard Date: Thu, 14 Nov 2024 16:07:13 +0100 Subject: [PATCH 127/136] Repaired export-dependency-graph property and dropped unsupported export-to-yaml property --- .../main/java/org/lflang/target/Target.java | 2 -- .../target/property/ExportToYamlProperty.java | 23 ------------------- .../cpp/CppStandaloneMainGenerator.kt | 4 +--- 3 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 core/src/main/java/org/lflang/target/property/ExportToYamlProperty.java diff --git a/core/src/main/java/org/lflang/target/Target.java b/core/src/main/java/org/lflang/target/Target.java index 30048f5a58..c99ed4a0d3 100644 --- a/core/src/main/java/org/lflang/target/Target.java +++ b/core/src/main/java/org/lflang/target/Target.java @@ -40,7 +40,6 @@ import org.lflang.target.property.CoordinationProperty; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ExportDependencyGraphProperty; -import org.lflang.target.property.ExportToYamlProperty; import org.lflang.target.property.ExternalRuntimePathProperty; import org.lflang.target.property.FilesProperty; import org.lflang.target.property.KeepaliveProperty; @@ -612,7 +611,6 @@ public void initialize(TargetConfig config) { CompilerProperty.INSTANCE, DockerProperty.INSTANCE, ExportDependencyGraphProperty.INSTANCE, - ExportToYamlProperty.INSTANCE, ExternalRuntimePathProperty.INSTANCE, NoRuntimeValidationProperty.INSTANCE, PrintStatisticsProperty.INSTANCE, diff --git a/core/src/main/java/org/lflang/target/property/ExportToYamlProperty.java b/core/src/main/java/org/lflang/target/property/ExportToYamlProperty.java deleted file mode 100644 index e592c3d8ec..0000000000 --- a/core/src/main/java/org/lflang/target/property/ExportToYamlProperty.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.lflang.target.property; - -/** - * If true, the resulting binary will output a yaml file describing the whole reactor structure of - * the program. - * - *

This option is currently only used for C++. This export function is a valuable tool for - * debugging LF programs and performing external analysis. - */ -public final class ExportToYamlProperty extends BooleanProperty { - - /** Singleton target property instance. */ - public static final ExportToYamlProperty INSTANCE = new ExportToYamlProperty(); - - private ExportToYamlProperty() { - super(); - } - - @Override - public String name() { - return "export-to-yaml"; - } -} diff --git a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt index 870f9ee267..782dada4b3 100644 --- a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneMainGenerator.kt @@ -6,7 +6,6 @@ import org.lflang.inferredType import org.lflang.lf.Parameter import org.lflang.lf.Reactor import org.lflang.target.property.ExportDependencyGraphProperty -import org.lflang.target.property.ExportToYamlProperty import org.lflang.target.property.FastProperty import org.lflang.target.property.TimeOutProperty import org.lflang.target.property.WorkersProperty @@ -101,12 +100,11 @@ class CppStandaloneMainGenerator( | | // assemble reactor program | e.assemble(); - ${" |".. if (targetConfig.get(ExportDependencyGraphProperty.INSTANCE)) "e.export_dependency_graph(\"${main.name}.dot\");" else ""} - ${" |".. if (targetConfig.get(ExportToYamlProperty.INSTANCE)) "e.dump_to_yaml(\"${main.name}.yaml\");" else ""} | | // start execution | auto thread = e.startup(); | thread.join(); + ${" |".. if (targetConfig.get(ExportDependencyGraphProperty.INSTANCE)) "e.export_dependency_graph(\"${main.name}.dot\");" else ""} | return 0; |} """.trimMargin() From 3990c7e1e508be2fbdf6ec5750aa5f4f820a6474 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 18 Nov 2024 11:43:20 -0800 Subject: [PATCH 128/136] Make macros available in methods --- .../lflang/generator/c/CMethodGenerator.java | 4 ++ test/C/src/MethodMacros.lf | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 test/C/src/MethodMacros.lf diff --git a/core/src/main/java/org/lflang/generator/c/CMethodGenerator.java b/core/src/main/java/org/lflang/generator/c/CMethodGenerator.java index acb6d348ce..dfb7cabdeb 100644 --- a/core/src/main/java/org/lflang/generator/c/CMethodGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CMethodGenerator.java @@ -7,6 +7,7 @@ import org.lflang.generator.CodeBuilder; import org.lflang.lf.Method; import org.lflang.lf.Reactor; +import org.lflang.util.StringUtil; /** * Collection of functions to generate C code to declare methods. @@ -60,6 +61,8 @@ public static String generateMethod( var body = ASTUtils.toText(method.getCode()); code.prSourceLineNumber(method, suppressLineDirectives); + // Define macros for functions such as lf_tag(), lf_time_logical(), lf_set(), etc. + code.pr("#include " + StringUtil.addDoubleQuotes(CCoreFilesUtils.getCTargetSetHeader())); code.prComment("Implementation of method " + method.getName() + "()"); code.pr(generateMethodSignature(method, tpr, types) + " {"); @@ -83,6 +86,7 @@ public static String generateMethod( code.pr(body); code.unindent(); code.pr("}"); + code.pr("#include " + StringUtil.addDoubleQuotes(CCoreFilesUtils.getCTargetSetUndefHeader())); code.prEndSourceLineNumber(suppressLineDirectives); return code.toString(); } diff --git a/test/C/src/MethodMacros.lf b/test/C/src/MethodMacros.lf new file mode 100644 index 0000000000..3eafeec608 --- /dev/null +++ b/test/C/src/MethodMacros.lf @@ -0,0 +1,48 @@ +// Test ability of methods to call each other and (recursively) themselves. +target C { + timeout: 10 ms +} + +reactor Fib { + input in: int + output out: int + state foo: int = 2 + + // Return the n-th Fibonacci number. + // Type name convention for ports is _class_method_t, all lowercase. + method fib(out: _fib_out_t*, n: int): int {= + int result = 1; + if (n > 1) result = add(fib(NULL, n-1), fib(NULL, n-2)); + if (out != NULL) { + lf_set(out, result); + lf_print("At elapsed time " PRINTF_TIME ", fib(%d) = %d", lf_time_logical_elapsed(), n, result); + } + return result; + =} + + method add(x: int, y: int): int {= + return x + y; + =} + + reaction(in) -> out {= + fib(out, in->value); + =} +} + +main reactor { + state count: int = 0 + timer t(0, 1 ms) + fib = new Fib() + + reaction(t) -> fib.in {= + lf_set(fib.in, self->count); + =} + + reaction(fib.out) {= + lf_print("fib(%d) = %d", self->count, fib.out->value); + int answers[] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89}; + if (fib.out->value != answers[self->count++]) { + lf_print_error_and_exit("Expected %d", answers[self->count-1]); + } + =} +} From 2a8e220f44eb57bd8283ac0af8517112ae8ff152 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Mon, 18 Nov 2024 22:00:00 -0800 Subject: [PATCH 129/136] Disable zephyr basic and concurrent tests --- .github/workflows/c-zephyr-tests.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/c-zephyr-tests.yml b/.github/workflows/c-zephyr-tests.yml index 2a69452506..85ad929d95 100644 --- a/.github/workflows/c-zephyr-tests.yml +++ b/.github/workflows/c-zephyr-tests.yml @@ -46,16 +46,16 @@ jobs: --tests org.lflang.tests.runtime.CZephyrTest.buildZephyrThreaded* core:integrationTestCodeCoverageReport ./.github/scripts/run-zephyr-tests.sh test/C/src-gen rm -rf test/C/src-gen - - name: Run basic tests - run: | - ./gradlew core:integrationTest --tests org.lflang.tests.runtime.CZephyrTest.buildBasic* core:integrationTestCodeCoverageReport - ./.github/scripts/run-zephyr-tests.sh test/C/src-gen - rm -rf test/C/src-gen - - name: Run concurrent tests - run: | - ./gradlew core:integrationTest --tests org.lflang.tests.runtime.CZephyrTest.buildConcurrent* core:integrationTestCodeCoverageReport - ./.github/scripts/run-zephyr-tests.sh test/C/src-gen - rm -rf test/C/src-gen + # - name: Run basic tests + # run: | + # ./gradlew core:integrationTest --tests org.lflang.tests.runtime.CZephyrTest.buildBasic* core:integrationTestCodeCoverageReport + # ./.github/scripts/run-zephyr-tests.sh test/C/src-gen + # rm -rf test/C/src-gen + # - name: Run concurrent tests + # run: | + # ./gradlew core:integrationTest --tests org.lflang.tests.runtime.CZephyrTest.buildConcurrent* core:integrationTestCodeCoverageReport + # ./.github/scripts/run-zephyr-tests.sh test/C/src-gen + # rm -rf test/C/src-gen - name: Run Zephyr board tests run: | ./gradlew core:integrationTest --tests org.lflang.tests.runtime.CZephyrTest.buildZephyrBoards* core:integrationTestCodeCoverageReport From 17687e7d2c4e9ec1ec7e33477dcf04632b2720b4 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 21 Nov 2024 15:00:50 -0800 Subject: [PATCH 130/136] Define LF_FILE_SEPARATOR in CMake --- .../java/org/lflang/federated/extensions/CExtensionUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java b/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java index 541ff67f74..12c93e0092 100644 --- a/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java +++ b/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java @@ -313,6 +313,8 @@ public static void generateCMakeInclude( "add_compile_definitions(LF_PACKAGE_DIRECTORY=\"" + fileConfig.srcPkgPath + "\")"); cmakeIncludeCode.pr( "add_compile_definitions(LF_SOURCE_GEN_DIRECTORY=\"" + fileConfig.getSrcGenPath() + "\")"); + cmakeIncludeCode.pr( + "add_compile_definitions(LF_FILE_SEPARATOR=\"" + File.separator + "\")"); try (var srcWriter = Files.newBufferedWriter(cmakeIncludePath)) { srcWriter.write(cmakeIncludeCode.getCode()); } From 554b34e58e7959746fa7cfc6897bb6aefc7916ed Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 21 Nov 2024 17:40:39 -0800 Subject: [PATCH 131/136] Silly formatting --- .../java/org/lflang/federated/extensions/CExtensionUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java b/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java index 12c93e0092..ad982431a2 100644 --- a/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java +++ b/core/src/main/java/org/lflang/federated/extensions/CExtensionUtils.java @@ -313,8 +313,7 @@ public static void generateCMakeInclude( "add_compile_definitions(LF_PACKAGE_DIRECTORY=\"" + fileConfig.srcPkgPath + "\")"); cmakeIncludeCode.pr( "add_compile_definitions(LF_SOURCE_GEN_DIRECTORY=\"" + fileConfig.getSrcGenPath() + "\")"); - cmakeIncludeCode.pr( - "add_compile_definitions(LF_FILE_SEPARATOR=\"" + File.separator + "\")"); + cmakeIncludeCode.pr("add_compile_definitions(LF_FILE_SEPARATOR=\"" + File.separator + "\")"); try (var srcWriter = Files.newBufferedWriter(cmakeIncludePath)) { srcWriter.write(cmakeIncludeCode.getCode()); } From f0db6ffedd8856ce4c90d35a8448e406ff08f91d Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 24 Nov 2024 07:28:53 -0800 Subject: [PATCH 132/136] Removed unused method --- .../launcher/FedLauncherGenerator.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java b/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java index 332ee003c6..1d340f44f4 100644 --- a/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java +++ b/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java @@ -513,26 +513,6 @@ private String getDistCode(Path remoteBase, FederateInstance federate) { + "'"); } - /** Return the body of a shell script file to compile the specified federate. */ - private String getCompileScript(Path remoteBase, FederateInstance federate) { - String baseDir = "~/" + remoteBase + "/" + fileConfig.name; - return String.join( - "\n", - "#!/bin/bash -l", // The -l argument makes this a login shell so PATH etc are inherited. - // FIXME: Put copied files in subdirectory federate.name - "cd " + remoteBase + "/fed-gen/" + fileConfig.name + "/src-gen/" + federate.name, - "rm -rf build", - "mkdir -p ~/" + remoteBase + "/log", - // >> appends stdout to the specified file, and 2>&1 appends stderr to the same file. - "mkdir -p build && cd build && cmake .. && make >> " - + baseDir - + "/" - + federate.name - + ".log 2>&1", - "mkdir -p ~/" + remoteBase + "/bin;\\", - "mv " + federate.name + " ~/" + remoteBase + "/bin;'"); - } - private String getUserHost(Object user, Object host) { if (user == null) { return host.toString(); From adf461b0f5c9a90c13cc243c952a7c719949f33c Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 24 Nov 2024 11:46:27 -0800 Subject: [PATCH 133/136] Use tar to transfer source files to remote host --- .../launcher/FedLauncherGenerator.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java b/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java index 1d340f44f4..10816dc111 100644 --- a/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java +++ b/core/src/main/java/org/lflang/federated/launcher/FedLauncherGenerator.java @@ -425,6 +425,7 @@ private String getDistCode(Path remoteBase, FederateInstance federate) { String logDirectory = "~/" + remoteBase + "/" + fileConfig.name + "/log"; String remoteBuildLogFileName = logDirectory + "/build.log"; String buildShellFileName = "build_" + federate.name + ".sh"; + String tarFileName = federate.name + ".tar.gz"; return String.join( "\n", "echo \"Making directory " @@ -443,18 +444,26 @@ private String getDistCode(Path remoteBase, FederateInstance federate) { + "; \\", " date >> " + remoteBuildLogFileName + ";", "'", - "pushd " + fileConfig.getSrcGenPath() + "/" + federate.name + " > /dev/null", - "echo \"**** Copying source files to host " - + getUserHost(federate.user, federate.host) - + "\"", - "scp -r * " + "pushd " + fileConfig.getSrcGenPath() + " > /dev/null", + "echo \"**** Bundling source files into " + tarFileName + "\"", + "tar -czf " + tarFileName + " --exclude build " + federate.name, + "echo \"**** Copying tarfile to host " + getUserHost(federate.user, federate.host) + "\"", + "scp -r " + + tarFileName + + " " + getUserHost(federate.user, federate.host) + ":" + remoteBase + "/" + fileConfig.name + "/" - + federate.name, + + tarFileName, + "rm " + tarFileName, + "ssh " + getUserHost(federate.user, federate.host) + " '\\", + " cd ~/" + remoteBase + "/" + fileConfig.name + "; \\", + " tar -xzf " + tarFileName + "; \\", + " rm " + tarFileName + ";", + "'", "popd > /dev/null", "echo \"**** Generating and executing compile.sh on host " + getUserHost(federate.user, federate.host) From 9bd8dacdba9de15f22dd784e4b9077f01c2625f2 Mon Sep 17 00:00:00 2001 From: Shaokai Jerry Lin Date: Fri, 29 Nov 2024 11:47:54 -0500 Subject: [PATCH 134/136] Remove pickScheduler() that chooses GEDF when deadlines are present --- .../org/lflang/generator/c/CGenerator.java | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index dda5c06d89..cfaddbb00e 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -741,31 +741,6 @@ else if (term.getParameter() != null) return result.toString(); } - /** Set the scheduler type in the target config as needed. */ - private void pickScheduler() { - // Don't use a scheduler that does not prioritize reactions based on deadlines - // if the program contains a deadline (handler). Use the GEDF_NP scheduler instead. - if (!targetConfig.get(SchedulerProperty.INSTANCE).prioritizesDeadline()) { - // Check if a deadline is assigned to any reaction - if (hasDeadlines(reactors)) { - if (!targetConfig.isSet(SchedulerProperty.INSTANCE)) { - SchedulerProperty.INSTANCE.override(targetConfig, Scheduler.GEDF_NP); - } - } - } - } - - private boolean hasDeadlines(List reactors) { - for (Reactor reactor : reactors) { - for (Reaction reaction : allReactions(reactor)) { - if (reaction.getDeadline() != null) { - return true; - } - } - } - return false; - } - /** * Copy all files or directories listed in the target property {@code files}, {@code * cmake-include}, and {@code _fed_setup} into the src-gen folder of the main .lf file @@ -2033,7 +2008,6 @@ protected boolean setUpGeneralParameters() { CompileDefinitionsProperty.INSTANCE.update(targetConfig, Map.of("MODAL_REACTORS", "TRUE")); } if (!targetConfig.get(SingleThreadedProperty.INSTANCE)) { - pickScheduler(); CompileDefinitionsProperty.INSTANCE.update( targetConfig, Map.of( From fbcd226bc9624cca7be17832e32910a86f14cef0 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 29 Nov 2024 10:39:48 -0800 Subject: [PATCH 135/136] Run spotless --- core/src/main/java/org/lflang/generator/c/CGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index cfaddbb00e..8adaa02eeb 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -102,7 +102,6 @@ import org.lflang.target.property.TracingProperty; import org.lflang.target.property.WorkersProperty; import org.lflang.target.property.type.PlatformType.Platform; -import org.lflang.target.property.type.SchedulerType.Scheduler; import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; import org.lflang.util.FlexPRETUtil; From 2f1c28e87d30c091314879fe205ddeac74be63d8 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 29 Nov 2024 17:44:37 -0800 Subject: [PATCH 136/136] Delete .github/FUNDING.yml We tried Open Collective but never received any funding, so I shut it down. --- .github/FUNDING.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 8066a501ff..0000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -open_collective: lingua-franca