Skip to content

Commit 61c70cd

Browse files
committed
starting point for alegbra synthesis
1 parent ae6d8da commit 61c70cd

4 files changed

Lines changed: 287 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package example.expression.algebra
2+
3+
import javax.inject.Inject
4+
5+
import com.github.javaparser.ast.CompilationUnit
6+
import expression.data.{Add, Eval, Lit}
7+
import expression.extensions.{Collect, Neg, PrettyP, Sub}
8+
import expression.{DomainModel, Exp, Operation}
9+
import org.combinators.cls.git.{EmptyResults, InhabitationController}
10+
import org.combinators.cls.interpreter.ReflectedRepository
11+
import org.combinators.templating.persistable.JavaPersistable._
12+
import org.webjars.play.WebJarsUtil
13+
import play.api.inject.ApplicationLifecycle
14+
15+
// https://bitbucket.org/yanlinwang/ep_trivially/src/7086d91a45c92c1522ec4d6f0618c574c2e2d562/JavaCode/EP/src/interfaceversion/InterfaceVersion.java?at=master&fileviewer=file-view-default
16+
17+
import scala.collection.JavaConverters._ // Needed for asJava
18+
19+
class Expression @Inject()(webJars: WebJarsUtil, applicationLifecycle: ApplicationLifecycle) extends InhabitationController(webJars, applicationLifecycle) {
20+
21+
// Configure the desired (sub)types and operations
22+
val base:DomainModel = new DomainModel(
23+
List[Exp](new Lit, new Add).asJava,
24+
List[Operation](new Eval).asJava
25+
)
26+
27+
val evolution_1:DomainModel = new DomainModel (
28+
List[Exp](new Sub).asJava,
29+
List.empty.asJava
30+
)
31+
32+
// evolution 2 (from Extensibility for the Masses example)
33+
val evolution_2:DomainModel = new DomainModel(evolution_1,
34+
List.empty.asJava,
35+
List[Operation](new PrettyP).asJava
36+
)
37+
38+
//model.data.add(new Neg)
39+
//model.data.add(new Sub)
40+
41+
// operations to have (including Eval)
42+
//model.ops.add(new PrettyP)
43+
//model.ops.add(new SimplifyExpr)
44+
//model.ops.add(new Collect)
45+
46+
lazy val repository = new ExpressionSynthesis(base) with Structure {}
47+
import repository._
48+
49+
lazy val Gamma = repository.init(ReflectedRepository(repository, classLoader = this.getClass.getClassLoader), base)
50+
51+
/** This needs to be defined, and it is set from Gamma. */
52+
lazy val combinatorComponents = Gamma.combinatorComponents
53+
54+
var jobs = Gamma.InhabitationBatchJob[CompilationUnit](ops(ops.base, new Eval))
55+
.addJob[CompilationUnit](exp(exp.base, new Exp))
56+
.addJob[CompilationUnit](ops(ops.algebra, new Eval))
57+
.addJob[CompilationUnit](ops(ops.algebra, new PrettyP))
58+
59+
// type interfaces (note: Exp is assumed above)
60+
61+
// add here as you are ready...
62+
// Initial object algebra interface for expressions: integers and addition
63+
64+
65+
66+
lazy val results = EmptyResults().addAll(jobs.run())
67+
68+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package example.expression.algebra
2+
3+
import com.github.javaparser.ast.CompilationUnit
4+
import example.expression.ExpressionDomain
5+
import expression._
6+
import org.combinators.cls.interpreter.combinator
7+
import org.combinators.cls.types._
8+
import org.combinators.templating.twirl.Java
9+
10+
import expression.data.Eval
11+
12+
import scala.collection.JavaConverters._
13+
14+
/** Future work to sanitize combinators to be independent of Exp. */
15+
class ExpressionSynthesis(override val domain:DomainModel) extends ExpressionDomain(domain) with SemanticTypes {
16+
17+
/** Generate from domain. USER NEEDS TO SPECIFY THESE EITHER AUTOMATICALLY OR MANUALLY */
18+
@combinator object BaseInterface {
19+
def apply() : CompilationUnit =
20+
Java(s"""
21+
|package algebra;
22+
|
23+
|// The evaluation interface
24+
|interface Eval {
25+
| int eval();
26+
|}
27+
|""".stripMargin).compilationUnit()
28+
29+
val semanticType:Type = ops(ops.base, new Eval)
30+
}
31+
@combinator object BaseExpClass {
32+
def apply() : CompilationUnit =
33+
Java(s"""
34+
interface ExpAlg<E> {
35+
| E lit(int x);
36+
| E add(E e1, E e2);
37+
|}
38+
|
39+
|""".stripMargin).compilationUnit()
40+
41+
val semanticType:Type = exp(exp.base, new Exp)
42+
}
43+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package example.expression.algebra
2+
3+
import expression.{Exp, Operation}
4+
import org.combinators.cls.types.syntax._
5+
import org.combinators.cls.types.{Constructor, Type}
6+
7+
8+
/**
9+
* These codify the semantic types used by the Expression problem as necessary
10+
* for the Algebra solution
11+
*
12+
* Extensibility for the Masses.
13+
* Practical Extensibility with Object Algebras. Bruno C. d. S. Oliveira and William R. Cook
14+
*
15+
* For any of these that are ever going to be translated directly into Java Type Names, you must
16+
* make them Constructor.
17+
*/
18+
trait SemanticTypes {
19+
20+
val driver:Type = 'Driver
21+
22+
// meta-concerns. When you have completed the definition of a constructor
23+
object generated {
24+
def apply (uniq:Type) : Constructor = 'Generated(uniq)
25+
26+
val complete: Type = 'Complete
27+
val initialized: Type = 'Initialized
28+
}
29+
//
30+
// object alg {
31+
// def apply (phase:Type) : Constructor = 'Alg(phase)
32+
//
33+
// val base:Type = 'Base
34+
// }
35+
36+
object exp {
37+
def apply (phase:Type, exp:Exp) : Constructor = 'Exp(phase, Constructor(exp.getClass.getSimpleName))
38+
39+
val base:Type = 'Base // initial class
40+
}
41+
42+
/**
43+
* Each operation has its own interface, assuming operation names are valid Java SimpleNames.
44+
*/
45+
object ops {
46+
def apply (phase:Type, op:Operation) : Constructor = 'Ops(phase, Constructor(op.getClass.getSimpleName))
47+
48+
val algebra:Type = 'Agl
49+
val base:Type = 'Base // initial class
50+
}
51+
52+
/**
53+
* Types appear here
54+
*/
55+
object data {
56+
def apply (uniq:String) : Constructor = 'Data(Constructor(uniq))
57+
}
58+
59+
object ep {
60+
def apply (phase:Type, exp:Exp) : Constructor = 'Ep(phase, Constructor(exp.getClass.getSimpleName))
61+
def apply (phase:Type, op:Operation) : Constructor = 'Op(phase, Constructor(op.getClass.getSimpleName))
62+
def apply (phase:Type, exp:Exp, op:Operation) : Constructor = {
63+
val crossP = exp.getClass.getSimpleName + op.getClass.getSimpleName
64+
'Op(phase, Constructor(crossP))
65+
}
66+
def apply (phase:Type, exp:Exp, ops:List[Operation]) : Constructor = {
67+
val crossP = exp.getClass.getSimpleName + ops.map(_.getClass.getSimpleName).mkString("")
68+
'Op(phase, Constructor(crossP))
69+
}
70+
def apply (phase:Type, ops:List[Operation]) : Constructor = {
71+
'Op(phase, Constructor(ops.map(_.getClass.getSimpleName).mkString("")))
72+
}
73+
74+
val interface:Type = 'Interface
75+
val defaultMethods:Type = 'Default
76+
val finalType:Type = 'Final
77+
}
78+
79+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package example.expression.algebra
2+
3+
import com.github.javaparser.ast.CompilationUnit
4+
import example.expression.j.MethodMapper
5+
import example.expression.{Base, ExpressionDomain}
6+
import expression._
7+
import expression.data.{Add, Eval, Lit}
8+
import expression.extensions._
9+
import expression.types.Types
10+
import org.combinators.cls.interpreter.{ReflectedRepository, combinator}
11+
import org.combinators.cls.types.Type
12+
import org.combinators.cls.types.syntax._
13+
import org.combinators.templating.twirl.Java
14+
15+
import scala.collection.JavaConverters._
16+
17+
/** Use Modularity2016 Java solution. Built from same domain model. */
18+
trait Structure extends Base with SemanticTypes with MethodMapper {
19+
20+
/** Add dynamic combinators as needed. */
21+
override def init[G <: ExpressionDomain](gamma: ReflectedRepository[G], model: DomainModel): ReflectedRepository[G] = {
22+
var updated = super.init(gamma, model)
23+
24+
updated
25+
}
26+
27+
28+
// implementations of operations: have to be defined. Note that these "raw Scala methods" could be replaced with tabular tool
29+
//
30+
//
31+
// Eval x Lit, Neg, Add, Sub ... Mult Divide ...
32+
// Print | pl, pn, pa, ps
33+
// Collect | cl, cn, ca, cs ...
34+
// Simplify | sl, sn, sa, ss ...
35+
36+
37+
def registerImpl (op:Operation, map:Map[Exp,String]): Unit = {
38+
map.keys.foreach {
39+
key =>
40+
addImpl(op, key, Java(map(key)).statements())
41+
}
42+
}
43+
44+
registerImpl(new Eval, Map(
45+
46+
new Lit -> "return e.getValue();",
47+
new Add -> "return e.getLeft().accept(this) + e.getRight().accept(this);",
48+
new Sub -> "return e.getLeft().accept(this) - e.getRight().accept(this);",
49+
new Mult -> "return e.getLeft().accept(this) * e.getRight().accept(this);",
50+
new Divd -> "return e.getLeft().accept(this) / e.getRight().accept(this);",
51+
new Neg -> "return -e.getExp().accept(this);"
52+
))
53+
54+
registerImpl(new PrettyP, Map(
55+
new Lit -> """return "" + e.getValue();""",
56+
new Add -> """return "(" + e.getLeft().accept(this) + "+" + e.getRight().accept(this) + ")";""",
57+
new Sub -> """return "(" + e.getLeft().accept(this) + "-" + e.getRight().accept(this) + ")";""",
58+
new Mult -> """return "(" + e.getLeft().accept(this) + "*" + e.getRight().accept(this) + ")";""",
59+
new Divd -> """return "(" + e.getLeft().accept(this) + "/" + e.getRight().accept(this) + ")";""",
60+
new Neg -> """return "-" + e.getExp().accept(this);"""
61+
))
62+
63+
64+
65+
66+
// sample Driver
67+
@combinator object Driver {
68+
def apply:CompilationUnit = Java(s"""
69+
|package ep;
70+
|
71+
|public class Driver {
72+
| public static void main(String[] args) {
73+
| System.out.println("======Add======");
74+
| Add add = new AddFinal(new LitFinal(7), new LitFinal(4));
75+
| System.out.println(add.eval());
76+
| System.out.println("======Sub======");
77+
| Sub sub = new SubFinal(new LitFinal(7), new LitFinal(4));
78+
| System.out.println(sub.eval());
79+
| System.out.println("======Print======");
80+
|
81+
| /* the line below causes compile-time error, if now commented out. */
82+
| //AddPrettyPFinal exp = new AddPrettyPFinal(new LitFinal(7)), new LitFinal(4));
83+
| AddPrettyPFinal prt = new AddPrettyPFinal(new LitPrettyPFinal(7), new LitPrettyPFinal(4));
84+
| System.out.println(prt.print() + " = " + prt.eval());
85+
| System.out.println("======CollectLiterals======");
86+
| AddCollectFinal addc = new AddCollectFinal(new LitCollectFinal(3), new LitCollectFinal(4));
87+
| System.out.println(addc.collectList().toString());
88+
| System.out.println("======Composition: Independent Extensibility======");
89+
| AddPrettyPCollectFinal addpc = new AddPrettyPCollectFinal(new LitPrettyPCollectFinal(3), new LitPrettyPCollectFinal(4));
90+
| System.out.println(addpc.print() + " = " + addpc.eval() + " Literals: " + addpc.collectList().toString());
91+
| }
92+
|}""".stripMargin).compilationUnit()
93+
94+
val semanticType:Type = driver
95+
}
96+
97+
}

0 commit comments

Comments
 (0)