Skip to content

Commit 889a155

Browse files
author
heineman
committed
Consolidated logic in SharedOO and OperationAsClass. These provide the workhorse for the business logic.
Only outlier is ObjectAlgebras since its AIP is decidedly different from all other OO approaches.
1 parent ff5de77 commit 889a155

File tree

15 files changed

+428
-433
lines changed

15 files changed

+428
-433
lines changed

Diff for: TODO.txt

+5-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ Trees that grow
2828
Notes: A1M3 for coco needs a full Exp and Factory. Why? Because otherwise merge accessing finalized instances from A1 are incompatible with
2929
the finalized instances from M3. Similar argument for M3W1 and even A1M3I2
3030

31-
3231
ifEqExpr <- ffiEquals.equalityCapabilities.areEqual(expType, expValue, zero)
3332
where expType is expType <- toTargetLanguageType(TypeRep.Double)
3433

@@ -37,4 +36,8 @@ It wasn't working because I had mistakenly used a type for "ep.Exp[FT]"
3736
ALgebra had to go back to its own "dataTypeCasesWithNewOperations" for some reason.
3837

3938
So Coco, Trivially and Algebra all have slightly different results and it REALLY makes me curious
40-
as to why
39+
as to why
40+
41+
============================
42+
43+
Runtime Dispatch FAILS whenever pass in a model. if we can fix this, then I can better integrate with OO code.

Diff for: core/src/main/scala/org/combinators/ep/approach/oo/CoCoClean.scala

+6-34
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ package org.combinators.ep.approach.oo /*DI:LI:AD*/
33
import org.combinators.ep.domain.abstractions.{DataTypeCase, Operation, TestCase, TypeRep}
44
import org.combinators.ep.domain.{GenericModel, abstractions}
55
import org.combinators.ep.generator.Command.Generator
6-
import org.combinators.ep.generator.communication.{ReceivedRequest, Request}
76
import org.combinators.ep.generator.paradigm.AnyParadigm.syntax.forEach
8-
import org.combinators.ep.generator.{AbstractSyntax, ApproachImplementationProvider, Command, EvolutionImplementationProvider, NameProvider, TestImplementationProvider, Understands, communication}
7+
import org.combinators.ep.generator.{AbstractSyntax, Command, EvolutionImplementationProvider, NameProvider, TestImplementationProvider, Understands, communication}
98
import org.combinators.ep.generator.paradigm.{AddImport, AnyParadigm, Apply, FindClass, Generics, ObjectOriented, ParametricPolymorphism, ResolveImport, AddTypeLookup}
109

11-
trait CoCoClean extends ApproachImplementationProvider {
10+
trait CoCoClean extends SharedOO {
1211
val paradigm: AnyParadigm
1312
val ooParadigm: ObjectOriented.WithBase[paradigm.type]
1413
val polymorphics: ParametricPolymorphism.WithBase[paradigm.type]
@@ -22,10 +21,6 @@ trait CoCoClean extends ApproachImplementationProvider {
2221
val finalizedTypeParameter: paradigm.syntax.Name = names.mangle("FT")
2322
val finalizedPackage: paradigm.syntax.Name = names.mangle("finalized")
2423
val getSelfMethod: paradigm.syntax.Name = names.mangle("getSelf")
25-
26-
def getter(attribute: abstractions.Attribute): paradigm.syntax.Name = {
27-
names.addPrefix("get", names.mangle(names.conceptNameOf(attribute)))
28-
}
2924
}
3025

3126
/**
@@ -464,41 +459,18 @@ trait CoCoClean extends ApproachImplementationProvider {
464459
import paradigm.methodBodyCapabilities._
465460
import ooParadigm.methodBodyCapabilities._
466461

467-
val properModel = latestModelDefiningNewFactoryType(domain) // not Exp but the Factory!
468-
.later(domain.findTypeCase(dataTypeCase).get)
469-
470462
for {
471463
_ <- setOperationMethodSignature(domain, finalizedType, operation)
472464
_ <- if (domain.operationsPresentEarlier(dataTypeCase).contains(operation)) {
473465
setOverride()
474466
} else {
475467
Command.skip[paradigm.MethodBodyContext]
476468
}
477-
arguments <- getArguments()
478-
self <- selfReference()
479-
attributes <- forEach(dataTypeCase.attributes) { attribute =>
480-
for {
481-
getterMethod <- getMember(self, ComponentNames.getter(attribute))
482-
getterCall <- apply(getterMethod, Seq.empty)
483-
} yield (attribute, getterCall)
484-
}
485-
receivedRequest =
486-
ReceivedRequest(
487-
onType = domain.baseDataType,
488-
tpeCase = dataTypeCase,
489-
selfReference = self,
490-
attributes = attributes.toMap,
491-
request = Request(
492-
op = operation,
493-
arguments = operation.parameters.zip(arguments.map(argument => argument._3)).toMap
494-
),
495-
model = Some(properModel)
496-
)
497-
result <- domainSpecific.logic(this)(receivedRequest)
469+
470+
result <- completeImplementation(domain.baseDataType, dataTypeCase, operation, domain, domainSpecific, attributeAccess=attributeGetterAccess)
498471
} yield result
499472
}
500473

501-
502474
def addDataTypeCaseInterfaces(domain: GenericModel, domainSpecific: EvolutionImplementationProvider[this.type]): Generator[paradigm.ProjectContext, Unit] = {
503475
val _newDataTypeCasesWithNewOperations = newDataTypeCasesWithNewOperations(domain)
504476

@@ -554,7 +526,7 @@ trait CoCoClean extends ApproachImplementationProvider {
554526

555527
// Add abstract getters if defined here
556528
_ <- forEach(if (domain.typeCases.contains(newDataTypeCase)) newDataTypeCase.attributes else List.empty) { attribute =>
557-
addAbstractMethod(ComponentNames.getter(attribute), setAttributeGetterSignature(domain, finalizedType, attribute))
529+
addAbstractMethod(getterName(attribute), setAttributeGetterSignature(domain, finalizedType, attribute))
558530
}
559531

560532
// Add methods for new operations
@@ -852,7 +824,7 @@ trait CoCoClean extends ApproachImplementationProvider {
852824
} else Command.lift[ooParadigm.ClassContext, paradigm.syntax.Type](baseTypeInterface)
853825

854826
_ <- addField(names.mangle(names.instanceNameOf(attribute)), attributeType)
855-
_ <- addMethod(ComponentNames.getter(attribute), makeAttributeGetter(domain, finalizedType, attribute))
827+
_ <- addMethod(getterName(attribute), makeAttributeGetter(domain, finalizedType, attribute))
856828
} yield ()
857829
}
858830

Diff for: core/src/main/scala/org/combinators/ep/approach/oo/ExtensibleVisitor.scala

+3-6
Original file line numberDiff line numberDiff line change
@@ -562,11 +562,8 @@ trait ExtensibleVisitor extends SharedOO with OperationAsClass {
562562
} yield ()
563563
}
564564

565-
def makeEachImplementation(domain:GenericModel, tpe: DataType,
566-
tpeCase: DataTypeCase,
567-
op: Operation,
568-
domainSpecific: EvolutionImplementationProvider[this.type]
569-
): Generator[MethodBodyContext, Option[Expression]] = {
565+
override def makeTypeCaseImplementation(tpe: DataType, tpeCase: DataTypeCase, op: Operation, domain:GenericModel,
566+
domainSpecific: EvolutionImplementationProvider[this.type]): Generator[MethodBodyContext, Option[Expression]] = {
570567
import paradigm.methodBodyCapabilities._
571568
import ooParadigm.methodBodyCapabilities._
572569
val properModel = latestModelDefiningOperatorClass(domain, tpeCase, op, domainSpecific).get
@@ -744,7 +741,7 @@ trait ExtensibleVisitor extends SharedOO with OperationAsClass {
744741
// for all that are not in primary parent
745742
_ <- forEach (typeCasesToDeclare) { tpe =>
746743
for {
747-
_ <- addMethod(visitor.visit, makeEachImplementation(domain, domain.baseDataType, tpe, operation, domainSpecific))
744+
_ <- addMethod(visitor.visit, makeTypeCaseImplementation(domain.baseDataType, tpe, operation, domain, domainSpecific))
748745

749746
// if dependent operations exist, those factories need to be generated as well later
750747
} yield ()

Diff for: core/src/main/scala/org/combinators/ep/approach/oo/Interpreter.scala

+24-46
Original file line numberDiff line numberDiff line change
@@ -275,16 +275,31 @@ sealed trait Interpreter extends SharedOO {
275275
!latestModelDefiningNewTypeInterface(domain).beforeOrEqual(definingModel)
276276
}
277277

278-
def makeInterpreterImplementation(domain: GenericModel,
279-
tpe: DataType,
280-
tpeCase: DataTypeCase,
281-
op: Operation,
282-
domainSpecific: EvolutionImplementationProvider[this.type]
283-
): Generator[MethodBodyContext, Option[Expression]] = {
278+
/**
279+
* Access attributes using default getter methods.
280+
*
281+
* @param attribute Data Type Case attribute to be accessed
282+
* @return
283+
*/
284+
def attributeInterpreterAccess(att:Attribute, tpeCase: DataTypeCase, domain:GenericModel, baseType:Option[paradigm.syntax.Type]) : Generator[MethodBodyContext, Expression] = {
285+
import ooParadigm.methodBodyCapabilities._
286+
287+
for {
288+
thisRef <- selfReference()
289+
att_member <- getMember(thisRef, names.mangle(names.instanceNameOf(att)))
290+
casted <- if (att.tpe.isModelBase(domain) && mustCastToAccess(domain, tpeCase)) { // only cast if Exp AND comes from older Exp
291+
castObject(baseType.get, att_member)
292+
} else {
293+
Command.lift[MethodBodyContext, Expression](att_member)
294+
}
295+
} yield casted
296+
}
297+
298+
def makeInterpreterImplementation(domain: GenericModel, tpe: DataType, tpeCase: DataTypeCase, op: Operation,
299+
domainSpecific: EvolutionImplementationProvider[this.type]): Generator[MethodBodyContext, Option[Expression]] = {
284300
import paradigm.methodBodyCapabilities._
285301
import ooParadigm.methodBodyCapabilities._
286302
import polymorphics.methodBodyCapabilities._
287-
val properModel = latestModelDefiningOperatorClass(domain, tpeCase, op, domainSpecific).get
288303

289304
for {
290305
_ <- makeInterpreterSignature(domain, op)
@@ -293,46 +308,9 @@ sealed trait Interpreter extends SharedOO {
293308
} else {
294309
Command.skip[MethodBodyContext]
295310
}
296-
thisRef <- selfReference()
297-
attAccessors: Seq[Expression] <- forEach (tpeCase.attributes) { att =>
298-
for {
299-
att_member <- getMember(thisRef, names.mangle(names.instanceNameOf(att)))
300-
mostSpecificExp <- mostSpecificBaseInterfaceType(domain)
301-
casted <- if (att.tpe.isModelBase(domain) && mustCastToAccess(domain, tpeCase)) { // only cast if Exp AND comes from older Exp
302-
castObject(mostSpecificExp, att_member)
303-
} else {
304-
Command.lift[MethodBodyContext, Expression](att_member)
305-
}
306-
} yield casted
307-
}
308-
309-
atts = tpeCase.attributes.zip(attAccessors).toMap
310311

311-
allArgs <- getArguments()
312-
castedArgs <- forEach(op.parameters.zip(allArgs)) { case (param,arg) =>
313-
for {
314-
mostSpecificExp <- mostSpecificBaseInterfaceType(domain)
315-
casted <- if (param.tpe.isModelBase(domain)) { // only cast if Exp
316-
castObject(mostSpecificExp, arg._3)
317-
} else {
318-
Command.lift[MethodBodyContext, Expression](arg._3)
319-
}
320-
} yield (param,casted)
321-
}
322-
323-
castedArgsMap = castedArgs.toMap
324-
325-
result <-
326-
domainSpecific.logic(this)(
327-
ReceivedRequest(
328-
tpe,
329-
tpeCase,
330-
thisRef,
331-
atts,
332-
Request(op, castedArgsMap),
333-
Some(properModel) // scala implementation for j8 needed this
334-
)
335-
)
312+
mostSpecificExp <- mostSpecificBaseInterfaceType(domain)
313+
result <- completeImplementation(domain.baseDataType, tpeCase, op, domain, domainSpecific, attributeAccess=attributeInterpreterAccess, baseType=Some(mostSpecificExp))
336314
} yield result
337315
}
338316

Diff for: core/src/main/scala/org/combinators/ep/approach/oo/ObjectAlgebras.scala

+3-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import org.combinators.ep.generator.paradigm.AnyParadigm.syntax.forEach
88
import org.combinators.ep.generator.paradigm._
99
import org.combinators.ep.generator._
1010

11-
11+
/**
12+
* Sufficiently different EP approach that this trait does not extend SharedOO
13+
*/
1214
trait ObjectAlgebras extends ApproachImplementationProvider {
1315
val paradigm: AnyParadigm
1416
val ooParadigm: ObjectOriented.WithBase[paradigm.type]
@@ -1002,12 +1004,6 @@ trait ObjectAlgebras extends ApproachImplementationProvider {
10021004
} yield (param, paramField)
10031005
}
10041006

1005-
dtParams <- forEach (dt.attributes) { param =>
1006-
for {
1007-
paramField <- getMember(selfRef, names.mangle(param.name))
1008-
} yield (new Parameter(param.name, param.tpe), paramField)
1009-
}
1010-
10111007
// An operation -- like equals(other) -- has an argument; the isXXX() operations have two arguments
10121008
// or one argument -- based on whether the corresponding data type has 1 or 2 attributes. Somehow have
10131009
// to collect together arguments to use within the ReceivedRequest(). Sometimes from the op... sometimes

Diff for: core/src/main/scala/org/combinators/ep/approach/oo/OperationAsClass.scala

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.combinators.ep.approach.oo /*DI:LI:AD*/
22

33
import org.combinators.ep.domain.GenericModel
4-
import org.combinators.ep.domain.abstractions.{DataType, DataTypeCase, Operation, Parameter}
4+
import org.combinators.ep.domain.abstractions.{Attribute, DataType, DataTypeCase, Operation, Parameter}
55
import org.combinators.ep.generator.Command.Generator
66
import org.combinators.ep.generator.paradigm.AnyParadigm.syntax.forEach
77
import org.combinators.ep.generator.paradigm.ObjectOriented
@@ -17,14 +17,9 @@ trait OperationAsClass extends ApproachImplementationProvider {
1717
import paradigm._
1818
import syntax._
1919

20-
/** Requires the capability of constructing an implementation */
21-
def makeImplementation(
22-
tpe: DataType,
23-
tpeCase: DataTypeCase,
24-
op: Operation,
25-
model: GenericModel,
26-
domainSpecific: EvolutionImplementationProvider[this.type]
27-
): Generator[MethodBodyContext, Option[Expression]]
20+
// Each AIP that includes this trait must provide implementation for how an entire method for a typecase is to be constructed.
21+
def makeTypeCaseImplementation(tpe: DataType, tpeCase: DataTypeCase, op: Operation, model: GenericModel,
22+
domainSpecific: EvolutionImplementationProvider[this.type]): Generator[MethodBodyContext, Option[Expression]]
2823

2924
/**
3025
* Constructor for an operation which MAY have parameters
@@ -88,16 +83,18 @@ trait OperationAsClass extends ApproachImplementationProvider {
8883
* @return
8984
* @see makeImplementation
9085
*/
91-
def operationClass(methodName:Name, op:Operation, model:GenericModel, typeCases:Seq[DataTypeCase], base:DataType, domainSpecific: EvolutionImplementationProvider[this.type]): Generator[ClassContext, Unit] = {
86+
def operationClass(methodName:Name, op:Operation, model:GenericModel, typeCases:Seq[DataTypeCase], base:DataType,
87+
domainSpecific: EvolutionImplementationProvider[this.type]): Generator[ClassContext, Unit] = {
9288
import ooParadigm.classCapabilities._
9389

9490
for {
9591
returnTpe <- toTargetLanguageType(op.returnType)
9692
_ <- resolveAndAddImport(returnTpe)
9793
_ <- addParamFields(op)
9894
_ <- addConstructor(makeOperationConstructor(op))
95+
9996
_ <- forEach (typeCases) { tpe =>
100-
addMethod(methodName, makeImplementation(base, tpe, op, model, domainSpecific))
97+
addMethod(methodName, makeTypeCaseImplementation(base, tpe, op, model, domainSpecific))
10198
}
10299
} yield ()
103100
}

0 commit comments

Comments
 (0)