Skip to content

Commit fe3a1cc

Browse files
authored
Merge pull request #6 from combinators/inbetween_cleanup
Inbetween cleanup
2 parents 5e86c08 + 14ebe5b commit fe3a1cc

443 files changed

Lines changed: 10559 additions & 11015 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Test code, update coverage, and release main branch
2+
3+
on: [ push, pull_request ]
4+
5+
jobs:
6+
release:
7+
runs-on: ubuntu-latest
8+
needs: [ ]
9+
steps:
10+
- uses: actions/checkout@v4.2.2
11+
- name: Check if we are head of main
12+
id: check_head_of_main
13+
run: |
14+
git fetch origin main &&
15+
MAIN=`git rev-parse origin/main` &&
16+
echo "::set-output name=head_of_main::$MAIN" &&
17+
CURRENT=`git rev-list -n 1 ${{ github.ref }} || echo "NOT_MAIN"` &&
18+
echo "::set-output name=current_job_ref::$CURRENT"
19+
- name: Set up JDK
20+
if: steps.check_head_of_main.outputs.head_of_main == steps.check_head_of_main.outputs.current_job_ref
21+
uses: actions/setup-java@v4
22+
with:
23+
distribution: temurin
24+
java-version: 21
25+
- name: Set up SBT
26+
if: steps.check_head_of_master.outputs.head_of_main == steps.check_head_of_main.outputs.current_job_ref
27+
uses: sbt/setup-sbt@v1.1.16
28+
with:
29+
sbt-runner-version: 1.10.11
30+
- name: Build and release
31+
if: steps.check_head_of_master.outputs.head_of_main == steps.check_head_of_main.outputs.current_job_ref
32+
env:
33+
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
34+
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
35+
SONA_USER: ${{ secrets.SONATYPE_USERNAME }}
36+
SONA_PASS: ${{ secrets.SONATYPE_PASSWORD }}
37+
PGP_SECRET: ${{ secrets.PGP_SECRET }}
38+
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
39+
PGP_KEY_HEX: ${{ secrets.PGP_KEY_HEX }}
40+
CI: github
41+
run: |
42+
git fetch --prune --unshallow --tags &&
43+
export GPG_TTY=$(tty) &&
44+
echo $PGP_SECRET | base64 -d | gpg --passphrase=$PGP_PASSPHRASE --yes --batch --pinentry-mode loopback --import &&
45+
export PATH=`pwd`/.github/bin:$PATH &&
46+
sbt cogen/ciReleaseTagNextVersion cogen/ciReleaseSonatype

January-2026-ToDo.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1. Visitor / M5 yields "key not found: Tree"
2+

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,20 +313,20 @@ family and are created using this same initial execution.
313313

314314
# Dependencies
315315

316-
EPCoGen is compiled with Scala version 2.12.17.
316+
EPCoGen is compiled with Scala 3.6.4 version.
317317

318-
All examples validated on Linux and Windows, using [sbt 1.7.2](https://www.scala-sbt.org/download#previous-releases)
318+
All examples validated on Linux and Windows, using [sbt 1.10.11](https://www.scala-sbt.org/download#previous-releases)
319319
, Scala version 2.12.17 and [Java 11 (OpenJDK)](https://openjdk.org/projects/jdk/11/).
320320

321-
Java code is generated using [JavaParser](https://github.com/javaparser/javaparser) version 3.19.0.
321+
Java code is generated using [JavaParser](https://github.com/javaparser/javaparser) version 3.26.4.
322322

323323
All JUnit tests are compiled using [JUnit 4.12](https://junit.org/junit4/) and Java compiler is directed to
324324
compile only assuming Java 1.8 compatibility.
325325

326326
The images above were generated using [GraphViz online](https://dreampuf.github.io/GraphvizOnline) based on
327327
output generated by our [GraphViz](core/src/main/scala/org/combinators/ep/domain/GraphViz.scala) code.
328328

329-
All generated Scala code is compiled using Scala version 3.3.3 and version
329+
All generated Scala code is compiled using Scala version 3.6.4 and version
330330
3.2.19 of the [Scalactic testing framework](https://www.scalatest.org/)
331331

332332
Python scripts require Python 3. Only the `scipy` package needs to be installed.

TECHNICAL.txt

Lines changed: 98 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,135 @@
1+
Codebase validated to work with
2+
3+
scalaVersion := "3.6.4"
4+
15
When you have a fresh clone of the git repository, enter the command `sbt compile` in the
26
top-level directory to compile EpCoGen. sbt will properly install all necessary software
37
libraries.
48

5-
We have tested with sbt versions of 1.7.1, 1.9.8, and 1.10.7.
9+
We have tested with sbt versions of 1.7.1, 1.9.8, 1.10.7, and 1.10.11.
10+
11+
We have tested with Java JDK 18.
612

713
If your Java version is too advanced for the sbt, you may need to add the
814
following to the build.st file to lower the associated Java version.
915

10-
javacOptions ++= Seq("-source", "11", "-target", "11"),
16+
javacOptions ++= Seq("-source", "11", "-target", "11")
1117

1218
And then you can install an openJDK version of Java 11 and use it by setting JAVA_HOME
13-
properly and/or configuring PATH variable appropriately.
19+
properly and/or configuring PATH variable appropriately. Grab the appropriate JDK 11
20+
from https://www.openlogic.com/openjdk-downloads
1421

1522
===================================
1623
Examples to run
1724
===================================
1825

19-
Sample commands to run. The first column shows the time it was launched, so to generate all
20-
evolution stages for all approaches on a Linux machine took just under an hour. And the
21-
compiling process for all code took just about three hours.
22-
23-
15:17 sbt language-java/run
24-
16:08 cd target/
25-
16:09 cd ep-java
26-
16:11 python3 ../../scripts/compare.py ../../scripts/systems/system-main.json >> REPORT
27-
16:12 python3 ../../scripts/compile.py
28-
19:08 python3 ../../scripts/process.py > STATISTICS
29-
19:09 cd ..
30-
19:11 sbt "helloWorld/runMain org.combinators.fibonacci.FibonacciWithLucasScalaDirectToDiskMain"
31-
19:13 cd target/fib
32-
19:13 cd scala/
33-
19:13 sbt test
26+
Sample commands to run. The first column shows the time to execute, so to generate all
27+
evolution stages for all approaches on a Linux machine took 22 minutes. The greatest
28+
cost is compiling everything. To compile the main example took about 2 hours since there
29+
are 27 evolutionary stages in the example.
30+
31+
Time Command
32+
00:02 sbt compile
33+
00:22 sbt language-java/run
3434

35+
cd target/ep-java
36+
00:01 python3 ../../scripts/compare.py ../../scripts/systems/system-main.json >> REPORT
37+
02:10 python3 ../../scripts/compile.py
38+
39+
00:01 python3 ../../scripts/process.py > STATISTICS
40+
cd ../..
41+
42+
---------------------------------
43+
Java Generation
3544
---------------------------------
3645

46+
The above generates all subdirectories that can now be compiled:
47+
48+
* D1D2 (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllD1D2"`)
49+
50+
cd target/ep-java-d1d2
51+
python3 ../../scripts/compare.py ../../scripts/systems/system-d1d2.json >> REPORT
52+
python3 ../../scripts/compile.py
53+
python3 ../../scripts/process.py > STATISTICS
54+
55+
* Main (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllMain"`)
56+
57+
cd target/ep-java
58+
python3 ../../scripts/compare.py ../../scripts/systems/system-main.json >> REPORT
59+
python3 ../../scripts/compile.py
60+
python3 ../../scripts/process.py > STATISTICS
61+
62+
* Merging (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllMerging"`)
63+
64+
cd target/ep-java-merging
65+
python3 ../../scripts/compare.py ../../scripts/systems/system-merging.json >> REPORT
66+
python3 ../../scripts/compile.py
67+
python3 ../../scripts/process.py > STATISTICS
68+
69+
* Extended (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllExtended"`)
70+
71+
cd target/ep-java-extended
72+
python3 ../../scripts/compare.py ../../scripts/systems/system-extended.json >> REPORT
73+
python3 ../../scripts/compile.py
74+
python3 ../../scripts/process.py > STATISTICS
75+
76+
* Third Alternate (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllThirdAlternate"`)
77+
78+
cd target/ep-java-third-alternate
79+
python3 ../../scripts/compare.py ../../scripts/systems/system-third-alternate.json >> REPORT
80+
python3 ../../scripts/compile.py
81+
python3 ../../scripts/process.py > STATISTICS
82+
83+
* System J (to just generated this, execute `sbt "language-java/runMain org.combinators.ep.language.java.GenerateAllJ"`)
84+
85+
cd target/ep-java-j
86+
python3 ../../scripts/compare.py ../../scripts/systems/system-j.json >> REPORT
87+
python3 ../../scripts/compile.py
88+
python3 ../../scripts/process.py > STATISTICS
89+
90+
3791
When generating the full Java implementations for all approaches and all evolution stages,
38-
there are 19,842 Java files containing 513,094 total lines of code.
92+
there are 17,469 Java files containing 432,215 total lines of code.
3993

4094
Using the CLOC utility, a more accurate picture appears. Of these only 3890 are truly
4195
unique files. The reason? Because the Expression Problem shows how to extend a system without
4296
modifying already created code, so it makes perfect sense that 80% of the code is duplicated!
4397

4498
% $CLOC --csv `find . -name "*.java"`
4599

46-
19842 text files.
47-
3890 unique files.
48-
15952 files ignored.
100+
17429 text files.
101+
3279 unique files.
102+
14150 files ignored.
49103

50-
files,language,blank,comment,code,"github.com/AlDanial/cloc v 1.86 T=17.31 s (224.7 files/s, 7917.7 lines/s)"
51-
3890,Java,27755,4,109292
52-
3890,SUM,27755,4,109292
104+
files,language,blank,comment,code,"github.com/AlDanial/cloc v 1.86 T=21.67 s (151.3 files/s, 4895.7 lines/s)"
105+
3279,Java,22368,4,83739
106+
3279,SUM,22368,4,83739
53107

54-
cloc reports 109,292 lines of code.
108+
cloc reports 83,739 lines of code.
55109

56110
Now run and turn off the uniqueness check:
57111

58112
% $CLOC --csv `find . -name "*.java"` --skip-uniqueness
59113

60-
19842,Java,117328,516,395250
114+
17429,Java,101632,420,327068
61115

62116
This reveals that 395,250 lines of Java code were generated.
63117

118+
---------------------------------
119+
ScalaGeneration
120+
---------------------------------
121+
sbt "language-newScala/runMain org.combinators.ep.language.scala.codegen.GenerateAllJ"
122+
sbt "language-newScala/runMain org.combinators.ep.language.scala.codegen.GenerateAllD1D2"
123+
sbt "language-newScala/runMain org.combinators.ep.language.scala.codegen.GenerateAllMain"
124+
sbt "language-newScala/runMain org.combinators.ep.language.scala.codegen.GenerateAllMerging"
125+
sbt "language-newScala/runMain org.combinators.ep.language.scala.codegen.GenerateAllExtended"
126+
127+
% $CLOC --csv `find ep-scala -name "*.scala"` `find ep-scala-d1d2 -name "*.scala"` `find ep-scala-extended -name "*.scala"` `find ep-scala-j -name "*.scala"` `find ep-scala-merging -name "*.scala"`
128+
129+
16770 text files.
130+
12217 unique files.
131+
4553 files ignored.
64132

133+
files,language,blank,comment,code,"github.com/AlDanial/cloc v 1.86 T=31.21 s (391.5 files/s, 14591.1 lines/s)"
134+
12217,Scala,242004,0,213356
135+
12217,SUM,242004,0,213356

TODO.txt

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,17 @@
1-
1. Generated test cases often exceed length allowed to method declarations.
1+
Generated test cases often exceed length allowed to method declarations.
22

33
a. As a stop-gap measure, these methods are arbitrarily split up, which means that the
44
visitorSideEffect has test cases that do not compile because of variables defined for
55
the visitor in one method but used in the other method.
66

7-
2. Functional -- continue progress from before
8-
9-
3.
7+
Functional -- continue progress from before
108

119
Scala-InBetween could add 'trait' capability and that could then
1210
be exposed as an option. This is high-level change and not
1311
object-oriented per se.
1412

1513
Add exceptions to newScala
1614

17-
Make CoGen stand alone
18-
19-
Note that Java equality in methods uses the .equals() which is a problem with primitive types. Thoughts?
20-
2115
Trees that grow
2216

23-
============================
24-
25-
Notes: A1M3 for coco needs a full Exp and Factory. Why? Because otherwise merge accessing finalized instances from A1 are incompatible with
26-
the finalized instances from M3. Similar argument for M3W1 and even A1M3I2
27-
28-
ifEqExpr <- ffiEquals.equalityCapabilities.areEqual(expType, expValue, zero)
29-
where expType is expType <- toTargetLanguageType(TypeRep.Double)
30-
31-
It wasn't working because I had mistakenly used a type for "ep.Exp[FT]"
32-
33-
ALgebra had to go back to its own "dataTypeCasesWithNewOperations" for some reason.
34-
35-
So Coco, Trivially and Algebra all have slightly different results and it REALLY makes me curious
36-
as to why
37-
38-
============================
39-
4017
Runtime Dispatch FAILS whenever pass in a model. if we can fix this, then I can better integrate with OO code.

core/src/main/scala/org/combinators/ep/approach/functional/Traditional.scala renamed to approach/src/main/scala/org/combinators/ep/approach/functional/Traditional.scala

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package org.combinators.ep.approach.functional /*DI:LI:AD*/
22

33
import org.combinators.ep.domain.GenericModel
4-
import org.combinators.ep.generator.{AbstractSyntax, ApproachImplementationProvider, Command, EvolutionImplementationProvider, NameProvider, Understands}
5-
import org.combinators.ep.generator.paradigm.control.{ConstructorPattern, Functional => FunControl}
6-
import Command.{Generator, _}
4+
import org.combinators.ep.generator.{ApproachImplementationProvider, EvolutionImplementationProvider}
5+
import org.combinators.cogen.{AbstractSyntax, Command, NameProvider, TypeRep, Understands}
6+
import Command.Generator
77
import cats.implicits._
8-
import org.combinators.ep.domain.abstractions.{DataType, DataTypeCase, Operation, Parameter, TypeRep}
8+
import org.combinators.cogen.paradigm.{AnyParadigm, FindType, Functional}
9+
import org.combinators.ep.domain.abstractions.{DataType, DataTypeCase, DomainTpeRep, Operation, Parameter}
910
import org.combinators.ep.generator.communication.{ReceivedRequest, Request, SendRequest}
10-
import org.combinators.ep.generator.paradigm.{AnyParadigm, FindType, Functional}
1111
import AnyParadigm.syntax._
12-
import org.combinators.ep.generator.paradigm.control.Functional.WithBase
12+
import org.combinators.cogen.paradigm.control.{ConstructorPattern, Functional as FunControl}
13+
import org.combinators.cogen.paradigm.control.Functional.WithBase
14+
import org.combinators.ep.domain.extensions._
1315

1416
trait Traditional extends ApproachImplementationProvider {
1517
val functional: Functional.WithBase[paradigm.type]
@@ -34,7 +36,7 @@ trait Traditional extends ApproachImplementationProvider {
3436
import paradigm.methodBodyCapabilities._
3537
import functional.methodBodyCapabilities._
3638
for {
37-
rt <- toTargetLanguageType(TypeRep.DataType(baseTpe))
39+
rt <- toTargetLanguageType(DomainTpeRep.DataType(baseTpe))
3840
_ <- resolveAndAddImport(rt)
3941
res <- instantiateType(rt, names.mangle(names.conceptNameOf(tpeCase)), args)
4042
} yield res
@@ -104,7 +106,7 @@ trait Traditional extends ApproachImplementationProvider {
104106
}
105107

106108
for {
107-
params <- forEach (Parameter(names.instanceNameOf(tpe), TypeRep.DataType(tpe)) +: op.parameters) { param: Parameter =>
109+
params <- forEach (Parameter(names.instanceNameOf(tpe), DomainTpeRep.DataType(tpe)) +: op.parameters) { (param: Parameter) =>
108110
for {
109111
pt <- toTargetLanguageType(param.tpe)
110112
_ <- resolveAndAddImport(pt)
@@ -116,7 +118,7 @@ trait Traditional extends ApproachImplementationProvider {
116118
_ <- resolveAndAddImport(returnType)
117119
_ <- setReturnType(returnType)
118120
args <- getArguments()
119-
onTpe <- toTargetLanguageType(TypeRep.DataType(tpe))
121+
onTpe <- toTargetLanguageType(DomainTpeRep.DataType(tpe))
120122
result <- {
121123
val matchGen = makeCases(tpe, cases, op, args.head._3, args.tail, domainSpecific)(_, _)
122124
patternMatch(
@@ -153,7 +155,7 @@ trait Traditional extends ApproachImplementationProvider {
153155
import functional.projectCapabilities._
154156
import functional.methodBodyCapabilities._ // Needed below
155157
import functional.typeCapabilities._ // Needed below
156-
val dtpeRep = TypeRep.DataType(domain.baseDataType)
158+
val dtpeRep = DomainTpeRep.DataType(domain.baseDataType)
157159
for {
158160
_ <- addTypeLookupForMethods(dtpeRep, domainTypeLookup(domain.baseDataType))
159161
_ <- addTypeLookupForTypes(dtpeRep, domainTypeLookup(domain.baseDataType))
@@ -182,11 +184,13 @@ object Traditional {
182184
(base: P)
183185
(nameProvider: NameProvider[base.syntax.Name],
184186
fun: Functional.WithBase[base.type],
185-
funControl: FunControl.WithBase[base.MethodBodyContext, base.type]): Traditional.WithParadigm[base.type] =
186-
new Traditional {
187-
override val paradigm: base.type = base
188-
override val names: NameProvider[base.syntax.Name] = nameProvider
189-
override val functional: Functional.WithBase[paradigm.type] = fun
190-
override val functionalControl: WithBase[paradigm.MethodBodyContext, paradigm.type] = funControl
191-
}
187+
funControl: FunControl.WithBase[base.MethodBodyContext, base.type]): Traditional.WithParadigm[base.type] = {
188+
case class Trad(
189+
override val paradigm: base.type,
190+
override val names: NameProvider[base.syntax.Name])(
191+
override val functional: Functional.WithBase[paradigm.type],
192+
override val functionalControl: WithBase[paradigm.MethodBodyContext, paradigm.type]
193+
) extends Traditional
194+
Trad(base, nameProvider)(fun, funControl)
195+
}
192196
}

0 commit comments

Comments
 (0)