Skip to content

Commit

Permalink
fix bug that prevented correct subtyping in the message type hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
ParsleyJ committed Apr 21, 2023
1 parent a6dda01 commit 17259fc
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,27 @@ import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.eclipse.xtext.testing.validation.ValidationTestHelper
import org.junit.Before
import org.eclipse.xtext.util.JavaVersion

/**
* Set of example tests (i.e., examples to help create new tests).
* Do not run, as they may fail on new Jadescript versions!
* Please run {@link TestSuite} to run all (valid) tests.
*/
@RunWith(XtextRunner)
@InjectWith(JadescriptInjectorProvider)
class GuideToTestJadeScript {
@Inject
ParseHelper<Model> parseHelper
@Inject extension ValidationTestHelper
@Inject extension ReflectExtensions
@Inject extension CompilationTestHelper
@Inject extension ParseHelper<Model>
@Inject extension CompilationTestHelper
@Before
public def setJavaVersion() {
javaVersion = JavaVersion.JAVA11
}

boolean parsingError

Expand Down Expand Up @@ -62,7 +73,7 @@ class GuideToTestJadeScript {
'''.parse.assertNoIssues
}

// 3) Test you correctly generated Java code
// 3) Test that the compiler correctly generated Java code
@Test
def void testGeneratedJavaCode() {
'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import org.eclipse.xtext.xbase.testing.CompilationTestHelper
import com.google.inject.Inject
import org.junit.Test
import org.junit.Assert
import org.junit.Before
import org.eclipse.xtext.util.JavaVersion

/*
* Tests to check if the validator correctly flags duplicate elements (variables, features, top-elements) as errors.
Expand All @@ -20,6 +22,10 @@ class TestDuplicatesCheckInValidator {
@Inject
ParseHelper<Model> parseHelper
@Inject extension CompilationTestHelper
@Before
public def setJavaVersion() {
javaVersion = JavaVersion.JAVA11
}

// Agent: test duplicate fields (check only parsing)
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import org.eclipse.xtext.xbase.testing.CompilationTestHelper
import com.google.inject.Inject
import org.junit.Test
import org.junit.Assert
import org.junit.Before
import org.eclipse.xtext.util.JavaVersion

/*
* Tests to check if the validator correctly flags duplicate elements (variables, features, top-elements) as errors.
Expand All @@ -20,6 +22,10 @@ class TypeInferrerTests {
@Inject ParseHelper<Model> parseHelper

@Inject extension CompilationTestHelper
@Before
public def setJavaVersion() {
javaVersion = JavaVersion.JAVA11
}



Expand Down Expand Up @@ -128,4 +134,61 @@ class TypeInferrerTests {
]
}

@Test
def void testMessageSubtyping(){
'''
module exampl
ontology JustAnAction
action TheAction
cyclic behaviour WaitingARequest
uses ontology JustAnAction
on message request TheAction do
log f1(message)
log f2(message)
function f1(m as RequestMessage of TheAction) as text do
return f2(m)
function f2(m as Message of TheAction) as text do
return (performative of m) as text
'''.compile[
var msg = ""
if(!errorsAndWarnings.isNullOrEmpty){
msg = errorsAndWarnings.get(0).message
}
Assert.assertTrue(msg, errorsAndWarnings.isNullOrEmpty)
]
}

@Test
def void testMessageSubtypingError(){
// inverted the type relationships of the arguments of f1 and f2
'''
module exampl
ontology JustAnAction
action TheAction
cyclic behaviour WaitingARequest
uses ontology JustAnAction
on message request TheAction do
log f1(message)
log f2(message)
function f1(m as Message of TheAction) as text do
return f2(m)
function f2(m as RequestMessage of TheAction) as text do
return (performative of m) as text
'''.compile[
var msg = ""
if(!errorsAndWarnings.isNullOrEmpty){
msg = errorsAndWarnings.get(0).message
}
Assert.assertFalse(msg, errorsAndWarnings.isNullOrEmpty)
]
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,7 @@ public void configureIScopeProviderDelegate(final Binder binder) {
.annotatedWith(Names.named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE))
.to(XImportSectionNamespaceScopeProvider.class);
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ private IJadescriptType getMessageType(
final TypeSolver typeSolver = module.get(TypeSolver.class);
final BuiltinTypeProvider builtins =
module.get(BuiltinTypeProvider.class);

final Maybe<String> baseTypeName =
messageTypeMaybe.__(MessageType::getBaseType);
final IJadescriptType contentType =
Expand All @@ -290,13 +291,20 @@ private IJadescriptType getMessageType(
final List<? extends TypeArgument> contentTypes;

if (!isExplicitContentType) {
contentTypes =
typeSolver.getDefaultTypeArguments(baseTypeName.toNullable());

if(baseTypeName.wrappedEquals("Message")){ //TODO
return builtins.anyMessage();
}

contentTypes = typeSolver.getDefaultTypeArguments(
baseTypeName.toNullable()
);
} else {
contentTypes = typeHelper.unpackTuple(contentType);
}

return baseTypeName
.__(typeSolver::getMessageTypeSchemaForPerformative)
.__(typeSolver::getMessageTypeSchemaForTypeName)
.__(f -> {
try {
return f.create(contentTypes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import it.unipr.ailab.maybe.utils.LazyInit;
import jade.core.AID;
import jade.lang.acl.ACLMessage;
import jadescript.content.JadescriptOntoElement;
import jadescript.core.message.*;
import jadescript.java.AgentEnv;
import jadescript.java.SideEffectsFlag;
Expand Down Expand Up @@ -61,13 +62,13 @@ public class BuiltinTypeProvider {
/*package-private*/ final LazyInit<JavaVoidType> tVoid =
fromModule(JavaVoidType.class);

@BuiltinType
@BuiltinType(JadescriptOntoElement.class)
/*package-private*/ final LazyInit<AnyOntologyElementType>
tAnyOntologyElement = fromModule(AnyOntologyElementType.class);

@BuiltinType
/*package-private*/ final LazyInit<AnyMessageType> tAnyMessage =
fromModule(AnyMessageType.class);
/*package-private*/ final LazyInit<BaseMessageType> tAnyMessage =
lazyInit(() -> message(covariant(anyOntologyElement())));

@BuiltinType(Number.class)
/*package-private*/ final LazyInit<NumberType> tNumber =
Expand Down Expand Up @@ -1923,7 +1924,7 @@ public AnyOntologyElementType anyOntologyElement() {
}


public AnyMessageType anyMessage() {
public BaseMessageType anyMessage() {
return tAnyMessage.get();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private void doInitialize() {
continue;
}

if(!Supplier.class.isAssignableFrom(declaredField.getType())){
if (!Supplier.class.isAssignableFrom(declaredField.getType())) {
throw new RuntimeException("Wrong type of the builtin-type " +
"field '" + declaredField.getName() + "'.");
}
Expand Down Expand Up @@ -141,11 +141,17 @@ private void registerBuiltinParametricType(
@Nullable MessageBuiltinType messageAnnotation
) {
for (Class<?> jvmClass : builtinTypeAnnotation.value()) {
final JvmTypeReference typeRef =
jvmTypeHelper.get().typeRef(jvmClass);
final String fqn = JvmTypeHelper.noGenericsTypeName(
jvmTypeHelper.get().typeRef(jvmClass)
.getQualifiedName('.')
typeRef.getQualifiedName('.')
);

final String simpleName = JvmTypeHelper.noGenericsTypeName(
typeRef.getSimpleName()
);


try {
final Supplier<ParametricTypeSchema<? extends IJadescriptType>>
parametricTypeSchemaSupplier =
Expand All @@ -164,7 +170,7 @@ private void registerBuiltinParametricType(
final Performative performative =
Performative.fromCode(messageAnnotation.value());

messageClassToPerformativeMap.put(fqn, performative);
messageClassToPerformativeMap.put(simpleName, performative);
performativeToMessageSubtypeMap.put(
performative,
Utils.castSupplier(parametricTypeSchemaSupplier)
Expand All @@ -186,7 +192,7 @@ private boolean isPackagePrivate(Field field) {
}


private void initializeIfNecessary() {
private void initializeIfRequired() {
if (!this.initialized) {
doInitialize();
}
Expand All @@ -195,7 +201,7 @@ private void initializeIfNecessary() {

/*package-private*/ Map<String, Supplier<? extends IJadescriptType>>
getTypeTable() {
initializeIfNecessary();
initializeIfRequired();
return this.typeTable;
}

Expand All @@ -204,28 +210,28 @@ private void initializeIfNecessary() {
String,
Supplier<ParametricTypeSchema<? extends IJadescriptType>>
> getParametricTypeTable() {
initializeIfNecessary();
initializeIfRequired();
return this.parametricTypeTable;
}


/*package-private*/ Map<String, Performative>
getMessageClassToPerformativeMap() {
initializeIfNecessary();
initializeIfRequired();
return messageClassToPerformativeMap;
}


/*package-private*/ Map<
Performative, Supplier<ParametricTypeSchema<? extends MessageType>>
> getPerformativeToMessageSubtypeMap() {
initializeIfNecessary();
initializeIfRequired();
return performativeToMessageSubtypeMap;
}


/*package-private*/ Map<String, Integer> getExpectedTypeParameters() {
initializeIfNecessary();
initializeIfRequired();
return expectedTypeParameters;
}

Expand All @@ -234,7 +240,7 @@ public void store(
JvmTypeReference input,
IJadescriptType output
) {
initializeIfNecessary();
initializeIfRequired();
typeTable.put(
input.getQualifiedName('.'),
() -> output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,32 +413,18 @@ public IJadescriptType fromJvmTypePermissive(


public ParametricTypeSchema<? extends MessageType>
getMessageTypeSchemaForPerformative(
String performative
) {
getMessageTypeSchemaForTypeName(String messageTypeName) {
return getMessageTypeSchemaForPerformative(
index.getMessageClassToPerformativeMap().get(performative)
index.getMessageClassToPerformativeMap().get(messageTypeName)
);
}


@SuppressWarnings("unchecked")
public List<TypeArgument> getDefaultTypeArguments(
String name
) {
if (name.equals("Message")) {
return List.of(builtinTypes.any(
"There are no type upper bounds for the content " +
"of a message of root type Message."
));
public List<TypeArgument> getDefaultTypeArguments(String messageTypeName) {

}
final Performative performative =
index.getMessageClassToPerformativeMap().get(name);

if (performative == null) {
return List.of();
}
final @Nullable Performative performative =
index.getMessageClassToPerformativeMap().get(messageTypeName);

final IJadescriptType contentBound =
getContentBoundForPerformative(performative);
Expand All @@ -453,8 +439,12 @@ public List<TypeArgument> getDefaultTypeArguments(


public IJadescriptType getContentBoundForPerformative(
Performative performative
@Nullable Performative performative
) {
if(performative == null){
return builtinTypes.any("");
}

final List<IJadescriptType> upperBounds =
index.getPerformativeToMessageSubtypeMap().get(performative)
.get().getUpperBounds();
Expand Down
Loading

0 comments on commit 17259fc

Please sign in to comment.