Skip to content

Commit

Permalink
Events/payloads (eclipse#344)
Browse files Browse the repository at this point in the history
* Implement Ringbuffers
* Better code generation for ringbuffers via transformation stage.
* Implement MQTT Subscribe
* Extend generated function definitions to allow other things of generated things
* Introduce literals as types in the model
* New ESI works
* make type checking more lenient for literal types, implement string size inference
* Strings in ringbuffers work!
* Receiving MQTT messages works!
* Add runtime test for payloads
* Fix ringbuffers that are not consumed: they need to have events pushed regardless
  • Loading branch information
wegendt-bosch authored and PriyaGovind committed Apr 15, 2020
1 parent c07d88b commit e3484e3
Show file tree
Hide file tree
Showing 135 changed files with 2,800 additions and 732 deletions.
3 changes: 2 additions & 1 deletion bundles/org.eclipse.mita.base/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ Require-Bundle: org.eclipse.xtext;visibility:=reexport,
com.google.guava,
org.eclipse.mita.library.extension,
org.eclipse.core.resources;bundle-version="3.12.0",
com.google.gson;bundle-version="2.2.4"
com.google.gson;bundle-version="2.2.4",
org.eclipse.xtext.ui
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Export-Package: io.protostuff,
io.protostuff.runtime,
Expand Down
43 changes: 40 additions & 3 deletions bundles/org.eclipse.mita.base/model/types.xcore
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class TypeReferenceSpecifier extends PresentTypeSpecifier {
val args = if(typeArguments.empty) {
""
} else {
"<" + typeArguments.map[if(it === null) {"null"} else {it.toString}].reduce[p1, p2| p1 + ", " + p2] + ">"
"<" + typeArguments.map[if(it === null) {"null"} else {it.toString}].reduce[p1, p2| p1 + ", " + p2] + ">" + (if(optional) {"?"} else {""})
}

val ref = eGet(TypesPackage.eINSTANCE.typeReferenceSpecifier_Type, false)
Expand All @@ -60,7 +60,14 @@ class TypeReferenceSpecifier extends PresentTypeSpecifier {
refText = refText ?: ""
refText = refText.trim

return refText + args;
val optionalModifier = if(optional) {
"?";
}
else {
""
}

return referenceModifiers.join + refText + optionalModifier + args;
}
}
class TypeReferenceLiteral extends Literal {
Expand Down Expand Up @@ -337,6 +344,12 @@ class Parameter extends TypedElement, NamedElement {
}
}

abstract class ExportableOperation extends Operation, Exportable {
op String toString() {
return super.toString();
}
}

abstract class Expression {
}
class ParameterWithDefaultValue extends Parameter {
Expand Down Expand Up @@ -415,14 +428,23 @@ class StructureType extends StructuralType, HasAccessors, Exportable {
}
}

class GeneratedFunctionDefinition extends ExportableOperation, GeneratedElement {
op String getId(){
return null;
}
op String toString() {
return super.toString();
}
}

class GeneratedType extends ComplexType, GeneratedElement, Exportable {
op String toString() {
super.toString
}
contains Operation constructor
}

class GeneratedTypeConstructor extends Operation, GeneratedObject {
class GeneratedTypeConstructor extends GeneratedFunctionDefinition, GeneratedObject {
contains transient TypeReferenceSpecifier generatedTypeSpecifier

op String getName() {
Expand All @@ -435,6 +457,16 @@ class GeneratedTypeConstructor extends Operation, GeneratedObject {
return "con_" + generatedType?.name
}

op boolean isExported() {
val generatedType = if(eContainer instanceof GeneratedType) {
eContainer as GeneratedType;
}
else {
return false;
}
return generatedType.isExported;
}

op TypeParameter[] getTypeParameters() {
return (eContainer as GeneratedType).typeParameters;
}
Expand Down Expand Up @@ -583,3 +615,8 @@ class CoercionExpression extends Expression {
}
}

class SystemResourceEvent extends Event {
String sizeInferrer
}


Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,16 @@ GeneratedType returns GeneratedType:
'generator' generator=STRING
'size-inferrer' sizeInferrer=STRING
('validator' validator=STRING)?
constructor = GeneratedTypeConstructor
(constructor = GeneratedTypeConstructor)?
';'
;

GeneratedTypeConstructor returns GeneratedTypeConstructor:
{GeneratedTypeConstructor}
'constructor' name='con' '(' (parameters+=GeneratedTypeParameter (',' parameters+=GeneratedTypeParameter)*)? ')'
('generator' generator=STRING)?
('size-inferrer' sizeInferrer=STRING)?
('validator' validator=STRING)?
;

GeneratedTypeParameter returns GeneratedTypeParameter:
Expand Down Expand Up @@ -156,6 +159,13 @@ ProductMember returns ProductMember:
name=ID ':' typeSpecifier=TypeSpecifier
;

SystemResourceEvent returns SystemResourceEvent:
'event' name=ID ((':' typeSpecifier=TypeSpecifier) | (typeSpecifier=NullTypeSpecifier)) ('{'
("size-inferrer" sizeInferrer=STRING)?
'}')?
;



/**
* BELOW THIS LINE
Expand Down Expand Up @@ -417,6 +427,7 @@ ReservedKeywords:
'catch' |
'checked' |
'constructor' |
'con' |
'do' |
'else' |
'enum' |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ class ExpressionUtils {
if(name == "self") {
return expr.arguments.head.value;
}
argIndex--;
}
}
if(argIndex === null || argIndex >= sortedArgs.length) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import org.eclipse.mita.base.expressions.StringLiteral
import org.eclipse.mita.base.expressions.TypeCastExpression
import org.eclipse.mita.base.expressions.UnaryOperator
import org.eclipse.mita.base.expressions.ValueRange
import org.eclipse.mita.base.types.Event
import org.eclipse.mita.base.types.ComplexType
import org.eclipse.mita.base.types.ExceptionTypeDeclaration
import org.eclipse.mita.base.types.Expression
Expand Down Expand Up @@ -128,6 +129,7 @@ class BaseConstraintFactory implements IConstraintFactory {
protected IScopeProvider scopeProvider;

public static final String GENERATOR_KEY = "generator";
public static final String VALIDATOR_KEY = "validator";
public static final String SIZE_INFERRER_KEY = "sizeInferrer";
public static final String PARENT_NAME_KEY = "parentName";
public static final String ECLASS_KEY = "eClass";
Expand Down Expand Up @@ -220,7 +222,9 @@ class BaseConstraintFactory implements IConstraintFactory {
}

protected def void computeConstraintsForChildren(ConstraintSystem system, EObject context) {
context.eContents.forEach[ system.computeConstraints(it) ]
for(EObject child: context.eContents) {
system.computeConstraints(child)
}
}

protected def computeParameterType(ConstraintSystem system, Operation function, Iterable<Parameter> parms) {
Expand Down Expand Up @@ -386,6 +390,10 @@ class BaseConstraintFactory implements IConstraintFactory {
return system.associate(refType, varOrFun);
}

protected dispatch def TypeVariable computeConstraints(ConstraintSystem system, Event event) {
return system.associate(system.computeConstraints(event.typeSpecifier), event);
}

protected def TypeVariable computeConstraintsForFunctionCall(ConstraintSystem system, EObject functionCall, EReference functionReference, String functionName, Iterable<Expression> argExprs, List<TypeVariable> candidates) {
return computeConstraintsForFunctionCall(system, functionCall, functionReference, functionName, system.computeArgumentConstraints(functionCall, functionName, argExprs), candidates);
}
Expand Down Expand Up @@ -818,6 +826,9 @@ class BaseConstraintFactory implements IConstraintFactory {
if(genType.sizeInferrer !== null) {
system.putUserData(result, SIZE_INFERRER_KEY, genType.sizeInferrer)
}
if(genType.validator !== null) {
system.putUserData(result, VALIDATOR_KEY, genType.validator);
}
system._defineUserData(genType as ComplexType, result);
}
protected dispatch def AbstractType doTranslateTypeDeclaration(ConstraintSystem system, GeneratedType genType) {
Expand Down Expand Up @@ -905,7 +916,7 @@ class BaseConstraintFactory implements IConstraintFactory {
// compute <a, b>
val ref = typeSpecifier.eGet(eRef, false)
val reftext = if(ref instanceof EObject && !(ref as EObject).eIsProxy) ref.toString() else null;
val typeName = reftext ?: NodeModelUtils.findNodesForFeature(typeSpecifier, TypesPackage.eINSTANCE.typeReferenceSpecifier_Type)?.head?.text?.trim;
val typeName = reftext ?: NodeModelUtils.findNodesForFeature(BaseUtils.computeOrigin(typeSpecifier), TypesPackage.eINSTANCE.typeReferenceSpecifier_Type)?.head?.text?.trim;
val typeArgTypes = typeArguments.map[system.computeConstraints(it) as AbstractType];
// since type specifiers reference something we don't always know the variance here
val typeArgs = typeArgTypes.map[it -> Variance.UNKNOWN].force;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class StdlibTypeRegistry {
public static val sigInstTypeQID = QualifiedName.create(#[/*"stdlib",*/ "siginst"]);
public static val modalityTypeQID = QualifiedName.create(#[/*"stdlib",*/ "modality"]);
public static val arrayTypeQID = QualifiedName.create(#[/*"stdlib",*/ "array"]);
public static val ringbufferTypeQID = QualifiedName.create(#[/*"stdlib",*/ "ringbuffer"]);
public static val plusFunctionQID = QualifiedName.create(#["stdlib", "__PLUS__"]);
public static val minusFunctionQID = QualifiedName.create(#["stdlib", "__MINUS__"]);
public static val timesFunctionQID = QualifiedName.create(#["stdlib", "__TIMES__"]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import org.eclipse.xtext.resource.IFragmentProvider
import org.eclipse.xtext.resource.impl.ListBasedDiagnosticConsumer
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider
import org.eclipse.xtext.scoping.IScopeProvider
import org.eclipse.xtext.ui.resource.LiveScopeResourceSetInitializer
import org.eclipse.xtext.util.CancelIndicator
import org.eclipse.xtext.util.Triple
import org.eclipse.xtext.xtext.XtextFragmentProvider
Expand Down Expand Up @@ -105,6 +106,9 @@ class MitaBaseResource extends LazyLinkingResource {
public final static String PROGRAM_EXT = ".mita"
public final static String PLATFORM_EXT = ".platform"

@Inject
protected LiveScopeResourceSetInitializer liveScopeResourceSetInitializer

override toString() {
val str = URI.toString;
val len = str.length();
Expand Down Expand Up @@ -187,10 +191,12 @@ class MitaBaseResource extends LazyLinkingResource {

public def generateLinkAndType(EObject model) {
val diagnosticsConsumer = new ListBasedDiagnosticConsumer();
model.eAllContents.filter(GeneratedObject).forEach [
it.generateMembers()
]
typeLinker.doActuallyClearReferences(model);
BaseUtils.ignoreChange(model, [
typeLinker.doActuallyClearReferences(model);
model.eAllContents.filter(GeneratedObject).forEach [
it.generateMembers()
]
])
typeLinker.linkModel(model, diagnosticsConsumer);
typeDependentLinker.linkModel(model, diagnosticsConsumer);
// size inference expects fully linked types,
Expand All @@ -215,7 +221,8 @@ class MitaBaseResource extends LazyLinkingResource {

timer.start("resourceDescriptions");
if (!resourceSet.loadOptions.containsKey(ResourceDescriptionsProvider.NAMED_BUILDER_SCOPE)) {
resourceSet.loadOptions.put(ResourceDescriptionsProvider.LIVE_SCOPE, true);
// resourceSet.loadOptions.put(ResourceDescriptionsProvider.LIVE_SCOPE, true);
liveScopeResourceSetInitializer.initialize(resourceSet);
}
val resourceDescriptions = resourceDescriptionsProvider.getResourceDescriptions(resourceSet);
val thisResourceDescription = resourceDescriptions.getResourceDescription(resource.URI);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import java.util.Random
import java.util.stream.Collectors
import java.util.stream.IntStream
import org.eclipse.core.runtime.Assert
import org.eclipse.mita.base.typesystem.types.AbstractType.Either
import org.eclipse.mita.base.util.Either
import org.eclipse.mita.base.typesystem.types.AbstractType.NameModifier

class NicerTypeVariableNamesForErrorMessages extends NameModifier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ class CoerciveSubtypeSolver implements IConstraintSolver {
return null;
].filterNull.force;
}
}) ?: #[];
})?.filterNull ?: #[];

return new TypeClassConstraintResolutionResult(Substitution.EMPTY, equalities + subtypeCheckResult.constraints, #[], coercions, typ, fun, distance + subtypeCheckResult.constraints.size);
}
Expand Down Expand Up @@ -875,6 +875,9 @@ class CoerciveSubtypeSolver implements IConstraintSolver {
if(object === null) {
return;
}
if(object.eIsProxy) {
return;
}
val uri = EcoreUtil.getURI(object);
system.coercions.put(uri, type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import org.eclipse.mita.base.typesystem.infra.TypeClass
import org.eclipse.mita.base.typesystem.infra.TypeClassProxy
import org.eclipse.mita.base.typesystem.serialization.SerializationAdapter
import org.eclipse.mita.base.typesystem.types.AbstractType
import org.eclipse.mita.base.typesystem.types.AbstractType.Either
import org.eclipse.mita.base.typesystem.types.AbstractType.NameModifier
import org.eclipse.mita.base.typesystem.types.BottomType
import org.eclipse.mita.base.typesystem.types.DependentTypeVariable
Expand All @@ -47,6 +46,7 @@ import org.eclipse.mita.base.typesystem.types.TypeHole
import org.eclipse.mita.base.typesystem.types.TypeVariable
import org.eclipse.mita.base.typesystem.types.TypeVariableProxy
import org.eclipse.mita.base.util.BaseUtils
import org.eclipse.mita.base.util.Either
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtext.diagnostics.Severity
import org.eclipse.xtext.naming.QualifiedName
Expand Down Expand Up @@ -375,7 +375,7 @@ class ConstraintSystem {

val typeVar = getTypeVariable(typeVarOrigin);
if(typeVar != t && t !== null) {
addConstraint(new EqualityConstraint(typeVar, t, new ValidationIssue(Severity.ERROR, '''«typeVarOrigin» must be of type "%2$s"''', typeVarOrigin, null, "")), toHead);
addConstraint(new EqualityConstraint(typeVar, t, new ValidationIssue(Severity.ERROR, '''«typeVarOrigin» (:: %1$s) must be of type "%2$s"''', typeVarOrigin, null, "")), toHead);
}
return typeVar;
}
Expand Down Expand Up @@ -502,8 +502,8 @@ class ConstraintSystem {
println('''introducing «uri»!''');
}
// explicitly set the origin to the resolved object, since the symbol table only contains proxies!
val tvIdx = this.getTypeVariable(it).idx;
return new TypeVariable(it, tvIdx) as AbstractType;
val tv = this.getTypeVariable(it);
return tv.replaceOrigin(it) as AbstractType;
].force;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ class Substitution {
}

def void addToContent(TypeVariable tv, AbstractType typ) {
if(tv.idx == 2679 && typ.toString == "uint32") {
print("")
}
content.put(tv.idx, typ);
idxToTypeVariable.put(tv.idx, tv);
val freeVars = typ.freeVars;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import org.eclipse.emf.ecore.EObject
import org.eclipse.mita.base.typesystem.infra.Tree
import org.eclipse.mita.base.typesystem.solver.ConstraintSystem
import org.eclipse.mita.base.typesystem.solver.Substitution
import org.eclipse.mita.base.util.Either
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor

@Accessors
abstract class AbstractType {
Expand Down Expand Up @@ -92,38 +92,7 @@ abstract class AbstractType {
def AbstractType modifyNames(NameModifier converter) {
map[it.modifyNames(converter)];
}

/* Either<LEFT, RIGHT> is the opposite of a Pair<A, B>. Let's compare them:
* val Pair<Integer, Boolean> pair = new Pair<>(1, true);
* val Either<Integer, Boolean> intLeft = new Left<>(1);
* val Either<Integer, Boolean> boolRight = new Right<>(true);
*
* now pair holds both 1 and true, where values of type Either<> hold only one of them.
* therefore one can look at pair as a much safer version of "Object",
* since there are only two possible values that it may be instead of all classes on the classpath.
*
* If this class is used more extensively we should add more functions like
* - isLeft/isRight,
* - map(Either<A,B>, A=>C, B=>D),
* - match(onLeft: A=>C, onRight: B=>C), and so on.
* For now instanceof is enough, since we use this only in TypeVariable.modifyNames.
*/
public static abstract class Either<LEFT, RIGHT> {
public static def <LEFT, RIGHT> Either<LEFT, RIGHT> left(LEFT l) {
return new Left(l);
}
public static def <LEFT, RIGHT> Either<LEFT, RIGHT> right(RIGHT r) {
return new Right(r);
}
}
@FinalFieldsConstructor
public static class Left<T, R> extends Either<T, R> {
public val T value;
}
@FinalFieldsConstructor
public static class Right<T, R> extends Either<T, R> {
public val R value;
}

// basically a typedef of (A ~ typeof(TypeVariable.uniqueId)) => A -> A
public static abstract class NameModifier implements IntFunction<Either<Integer, String>> {
}
Expand Down
Loading

0 comments on commit e3484e3

Please sign in to comment.