diff --git a/api/proto/sysml.pb.go b/api/proto/sysml.pb.go index 20790fe15..be5e1161b 100644 --- a/api/proto/sysml.pb.go +++ b/api/proto/sysml.pb.go @@ -3888,6 +3888,7 @@ type Value struct { // *Value_Vector // *Value_VectorQuantity // *Value_MeasurementRef + // *Value_Infinity Kind isValue_Kind `protobuf_oneof:"kind"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -4065,6 +4066,15 @@ func (x *Value) GetMeasurementRef() *MeasurementRef { return nil } +func (x *Value) GetInfinity() bool { + if x != nil { + if x, ok := x.Kind.(*Value_Infinity); ok { + return x.Infinity + } + } + return false +} + type isValue_Kind interface { isValue_Kind() } @@ -4131,6 +4141,13 @@ type Value_MeasurementRef struct { MeasurementRef *MeasurementRef `protobuf:"bytes,15,opt,name=measurement_ref,json=measurementRef,proto3,oneof"` // a unit by itself, no magnitude } +type Value_Infinity struct { + // The unbounded value `*`, which is no number and no string: ordered above + // every finite magnitude and refused by arithmetic. Always true when set, + // as DocumentValue.infinity is. + Infinity bool `protobuf:"varint,16,opt,name=infinity,proto3,oneof"` +} + func (*Value_IntValue) isValue_Kind() {} func (*Value_RealValue) isValue_Kind() {} @@ -4161,6 +4178,8 @@ func (*Value_VectorQuantity) isValue_Kind() {} func (*Value_MeasurementRef) isValue_Kind() {} +func (*Value_Infinity) isValue_Kind() {} + // Array is a Collections::Array: its elements flattened in row-major order // under its dimensions, compared by content rather than by the object read. type Array struct { @@ -6813,7 +6832,7 @@ const file_sysml_proto_rawDesc = "" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + "\x04type\x18\x02 \x01(\tR\x04type\x12\"\n" + "\x05value\x18\x03 \x01(\v2\f.sysml.ValueR\x05value\x12\x12\n" + - "\x04unit\x18\x04 \x01(\tR\x04unit\"\x81\x05\n" + + "\x04unit\x18\x04 \x01(\tR\x04unit\"\x9f\x05\n" + "\x05Value\x12\x1d\n" + "\tint_value\x18\x01 \x01(\x03H\x00R\bintValue\x12\x1f\n" + "\n" + @@ -6833,7 +6852,8 @@ const file_sysml_proto_rawDesc = "" + "\x05array\x18\f \x01(\v2\f.sysml.ArrayH\x00R\x05array\x12'\n" + "\x06vector\x18\r \x01(\v2\r.sysml.VectorH\x00R\x06vector\x12@\n" + "\x0fvector_quantity\x18\x0e \x01(\v2\x15.sysml.VectorQuantityH\x00R\x0evectorQuantity\x12@\n" + - "\x0fmeasurement_ref\x18\x0f \x01(\v2\x15.sysml.MeasurementRefH\x00R\x0emeasurementRefB\x06\n" + + "\x0fmeasurement_ref\x18\x0f \x01(\v2\x15.sysml.MeasurementRefH\x00R\x0emeasurementRef\x12\x1c\n" + + "\binfinity\x18\x10 \x01(\bH\x00R\binfinityB\x06\n" + "\x04kind\"Q\n" + "\x05Array\x12\x1e\n" + "\n" + @@ -7373,6 +7393,7 @@ func file_sysml_proto_init() { (*Value_Vector)(nil), (*Value_VectorQuantity)(nil), (*Value_MeasurementRef)(nil), + (*Value_Infinity)(nil), } file_sysml_proto_msgTypes[54].OneofWrappers = []any{ (*Quantity_IntMagnitude)(nil), diff --git a/api/proto/sysml.proto b/api/proto/sysml.proto index 56295b092..9ff7359ae 100644 --- a/api/proto/sysml.proto +++ b/api/proto/sysml.proto @@ -700,6 +700,10 @@ message Value { Vector vector = 13; // numeric components, never a sequence VectorQuantity vector_quantity = 14; // components each with their unit MeasurementRef measurement_ref = 15; // a unit by itself, no magnitude + // The unbounded value `*`, which is no number and no string: ordered above + // every finite magnitude and refused by arithmetic. Always true when set, + // as DocumentValue.infinity is. + bool infinity = 16; } } diff --git a/changes/unreleased/infinity-and-metadata-values.added.md b/changes/unreleased/infinity-and-metadata-values.added.md new file mode 100644 index 000000000..d445c0513 --- /dev/null +++ b/changes/unreleased/infinity-and-metadata-values.added.md @@ -0,0 +1,9 @@ +- **`*` is a value.** In an expression position `*` evaluates to the unbounded value: it exceeds + every finite Integer, Real and Natural, equals itself, prints as `*` in the REPL and in traces, + and crosses gRPC on its own `Value.infinity` arm under the `infinity_value` capability — never + as the ordinary string `"*"`. Arithmetic over it is refused with a typed error naming the + operation rather than an infinity or a NaN. +- **`elem.metadata` reads an element's metadata.** `ref.metadata` yields the metadata annotating + the element as a sequence of metadata instances, in declaration order, with the feature values + the annotation body binds and the metadata type's own defaults where it binds none. An element + with no metadata yields the empty sequence, and reading metadata off a value is a typed error. diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java index 3ea930d94..9105e27a4 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java @@ -47,6 +47,9 @@ public final class Capabilities { /** A bare measurement unit ({@code SI::m}, {@code m / s}) travels as itself rather than as an unsupported null. */ public static final String MEASUREMENT_REFS = "measurement_refs"; + /** The unbounded value {@code *} travels as itself rather than as an unsupported null. */ + public static final String INFINITY_VALUE = "infinity_value"; + /** The {@code ApplyEdits} RPC edits a parsed model's own source. */ public static final String APPLY_EDITS = "apply_edits"; diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Value.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Value.java index 5273b4c34..d0c816efc 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Value.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Value.java @@ -67,6 +67,14 @@ record NullValue() implements Value {} */ record UnsetValue() implements Value {} + /** + * The unbounded value {@code *}: no number, ordered above every finite magnitude. + * + *

Only a service advertising the {@code infinity_value} capability reports it as itself rather + * than as an unsupported {@link NullValue}. + */ + record InfinityValue() implements Value {} + /** * A reference to a runtime instance, by the id the service assigned it. * diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java index 14882906f..093d32821 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java @@ -54,6 +54,7 @@ public static Optional value(org.openmbee.opensysml.proto.Value value) { case QUANTITY -> Optional.of(new Value.QuantityValue(quantity(value.getQuantity()))); case ENUM_LITERAL -> Optional.of(new Value.EnumerationValue(literal(value.getEnumLiteral()))); case UNSET -> Optional.of(new Value.UnsetValue()); + case INFINITY -> Optional.of(infinity(value)); case ARRAY -> Optional.of(array(value.getArray())); case VECTOR -> Optional.of(vector(value.getVector())); case VECTOR_QUANTITY -> Optional.of(vectorQuantity(value.getVectorQuantity())); @@ -62,6 +63,17 @@ public static Optional value(org.openmbee.opensysml.proto.Value value) { }; } + /** Only an asserted arm carries the unbounded value. */ + private static Value infinity(org.openmbee.opensysml.proto.Value value) { + if (!value.getInfinity()) { + throw new TransportException( + "the service answered a malformed value: the infinity arm states no value unless it is" + + " true", + null); + } + return new Value.InfinityValue(); + } + private static Value array(org.openmbee.opensysml.proto.Array array) { List elements = new ArrayList<>(array.getElementsCount()); for (org.openmbee.opensysml.proto.Value element : array.getElementsList()) { diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java index 40c5f03e6..1a843e626 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java @@ -699,7 +699,7 @@ public static void registerAllExtensions( "\030\001 \001(\tR\005lower\022\024\n\005upper\030\002 \001(\tR\005upper\"o\n\rA" + "ttributeInfo\022\022\n\004name\030\001 \001(\tR\004name\022\022\n\004type" + "\030\002 \001(\tR\004type\022\"\n\005value\030\003 \001(\0132\014.sysml.Valu" + - "eR\005value\022\022\n\004unit\030\004 \001(\tR\004unit\"\201\005\n\005Value\022\035" + + "eR\005value\022\022\n\004unit\030\004 \001(\tR\004unit\"\237\005\n\005Value\022\035" + "\n\tint_value\030\001 \001(\003H\000R\010intValue\022\037\n\nreal_va" + "lue\030\002 \001(\001H\000R\trealValue\022\037\n\nbool_value\030\003 \001" + "(\010H\000R\tboolValue\022#\n\014string_value\030\004 \001(\tH\000R" + @@ -715,178 +715,179 @@ public static void registerAllExtensions( "orH\000R\006vector\022@\n\017vector_quantity\030\016 \001(\0132\025." + "sysml.VectorQuantityH\000R\016vectorQuantity\022@" + "\n\017measurement_ref\030\017 \001(\0132\025.sysml.Measurem" + - "entRefH\000R\016measurementRefB\006\n\004kind\"Q\n\005Arra" + - "y\022\036\n\ndimensions\030\001 \003(\003R\ndimensions\022(\n\010ele" + - "ments\030\002 \003(\0132\014.sysml.ValueR\010elements\"6\n\006V" + - "ector\022,\n\ncomponents\030\001 \003(\0132\014.sysml.ValueR" + - "\ncomponents\"A\n\016VectorQuantity\022/\n\ncompone" + - "nts\030\001 \003(\0132\017.sysml.QuantityR\ncomponents\";" + - "\n\007Complex\022\022\n\004real\030\001 \001(\001R\004real\022\034\n\timagina" + - "ry\030\002 \001(\001R\timaginary\"g\n\013EnumLiteral\022\035\n\nli" + - "teral_id\030\001 \001(\tR\tliteralId\022%\n\016enumeration" + - "_id\030\002 \001(\tR\renumerationId\022\022\n\004name\030\003 \001(\tR\004" + - "name\"9\n\rValueSequence\022(\n\010elements\030\001 \003(\0132" + - "\014.sysml.ValueR\010elements\"\251\001\n\010Quantity\022%\n\r" + - "int_magnitude\030\001 \001(\003H\000R\014intMagnitude\022\'\n\016r" + - "eal_magnitude\030\002 \001(\001H\000R\rrealMagnitude\022\022\n\004" + - "unit\030\003 \001(\tR\004unit\022,\n\tunit_term\030\004 \001(\0132\017.sy" + - "sml.UnitTermR\010unitTermB\013\n\tmagnitude\"k\n\016M" + - "easurementRef\022\022\n\004unit\030\001 \001(\tR\004unit\022,\n\tuni" + - "t_term\030\002 \001(\0132\017.sysml.UnitTermR\010unitTerm\022" + - "\027\n\007unit_id\030\003 \001(\tR\006unitId\"q\n\010UnitTerm\022\033\n\t" + - "scale_num\030\001 \001(\001R\010scaleNum\022\033\n\tscale_den\030\002" + - " \001(\001R\010scaleDen\022+\n\007factors\030\003 \003(\0132\021.sysml." + - "UnitFactorR\007factors\"A\n\nUnitFactor\022\027\n\007uni" + - "t_id\030\001 \001(\tR\006unitId\022\032\n\010exponent\030\002 \001(\001R\010ex" + - "ponent\"c\n\nDiagnostic\022\032\n\010severity\030\001 \001(\tR\010" + - "severity\022\030\n\007message\030\002 \001(\tR\007message\022\037\n\004sp" + - "an\030\003 \001(\0132\013.sysml.SpanR\004span\"\212\001\n\004Span\022\022\n\004" + - "file\030\001 \001(\tR\004file\022\035\n\nstart_line\030\002 \001(\005R\tst" + - "artLine\022\033\n\tstart_col\030\003 \001(\005R\010startCol\022\031\n\010" + - "end_line\030\004 \001(\005R\007endLine\022\027\n\007end_col\030\005 \001(\005" + - "R\006endCol\"\023\n\021ServerInfoRequest\"R\n\022ServerI" + - "nfoResponse\022\030\n\007version\030\001 \001(\tR\007version\022\"\n" + - "\014capabilities\030\002 \003(\tR\014capabilities\"p\n\014Que" + - "ryRequest\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash" + - "\022\"\n\005query\030\002 \001(\0132\014.sysml.QueryR\005query\022\035\n\n" + - "oslc_query\030\003 \001(\tR\toslcQuery\"F\n\rQueryResp" + - "onse\0225\n\010elements\030\001 \003(\0132\031.sysml.QueryResu" + - "ltElementR\010elements\"^\n\005Query\022\024\n\005scope\030\001 " + - "\003(\tR\005scope\022\026\n\006select\030\002 \003(\tR\006select\022\'\n\005wh" + - "ere\030\003 \001(\0132\021.sysml.ConstraintR\005where\"\222\001\n\n" + - "Constraint\022:\n\tprimitive\030\001 \001(\0132\032.sysml.Pr" + - "imitiveConstraintH\000R\tprimitive\022:\n\tcompos" + - "ite\030\002 \001(\0132\032.sysml.CompositeConstraintH\000R" + - "\tcompositeB\014\n\nconstraint\"\227\001\n\023PrimitiveCo" + - "nstraint\022\030\n\007inverse\030\001 \001(\010R\007inverse\022\032\n\010pr" + - "operty\030\002 \001(\tR\010property\0224\n\010operator\030\003 \001(\016" + - "2\030.sysml.PrimitiveOperatorR\010operator\022\024\n\005" + - "value\030\004 \003(\tR\005value\"~\n\023CompositeConstrain" + - "t\0224\n\010operator\030\001 \001(\0162\030.sysml.CompositeOpe" + - "ratorR\010operator\0221\n\nconstraint\030\002 \003(\0132\021.sy" + - "sml.ConstraintR\nconstraint\"\302\001\n\022QueryResu" + - "ltElement\022\016\n\002id\030\001 \001(\tR\002id\022\022\n\004type\030\002 \001(\tR" + - "\004type\022I\n\nproperties\030\003 \003(\0132).sysml.QueryR" + - "esultElement.PropertiesEntryR\nproperties" + - "\032=\n\017PropertiesEntry\022\020\n\003key\030\001 \001(\tR\003key\022\024\n" + - "\005value\030\002 \001(\tR\005value:\0028\001\"\220\001\n\nSweepRange\022\034" + - "\n\tparameter\030\001 \001(\tR\tparameter\022\"\n\005start\030\002 " + - "\001(\0132\014.sysml.ValueR\005start\022\036\n\003end\030\003 \001(\0132\014." + - "sysml.ValueR\003end\022 \n\004step\030\004 \001(\0132\014.sysml.V" + - "alueR\004step\"\244\003\n\017RunSweepRequest\022\035\n\nmodel_" + - "hash\030\001 \001(\tR\tmodelHash\022\033\n\tsymbol_id\030\002 \001(\t" + - "R\010symbolId\022*\n\021subject_symbol_id\030\003 \001(\tR\017s" + - "ubjectSymbolId\022*\n\targuments\030\004 \003(\0132\014.sysm" + - "l.ValueR\targuments\022S\n\017named_arguments\030\005 " + - "\003(\0132*.sysml.RunSweepRequest.NamedArgumen" + - "tsEntryR\016namedArguments\022)\n\006ranges\030\006 \003(\0132" + - "\021.sysml.SweepRangeR\006ranges\022\030\n\007samples\030\007 " + - "\001(\003R\007samples\022\022\n\004seed\030\010 \001(\004R\004seed\032O\n\023Name" + - "dArgumentsEntry\022\020\n\003key\030\001 \001(\tR\003key\022\"\n\005val" + - "ue\030\002 \001(\0132\014.sysml.ValueR\005value:\0028\001\"\210\002\n\010Sw" + - "eepRow\022)\n\006inputs\030\001 \003(\0132\021.sysml.CalcOutpu" + - "tR\006inputs\022+\n\007outputs\030\002 \003(\0132\021.sysml.CalcO" + - "utputR\007outputs\022*\n\010verdicts\030\003 \003(\0132\016.sysml" + - ".VerdictR\010verdicts\022%\n\016elapsed_micros\030\004 \001" + - "(\003R\relapsedMicros\022\024\n\005error\030\005 \001(\tR\005error\022" + - ";\n\016failure_reason\030\006 \001(\0162\024.sysml.FailureR" + - "easonR\rfailureReason\"\274\002\n\020RunSweepRespons" + - "e\022#\n\004rows\030\001 \003(\0132\017.sysml.SweepRowR\004rows\022\036" + - "\n\nparameters\030\002 \003(\tR\nparameters\022\030\n\007sample" + - "d\030\003 \001(\010R\007sampled\022\022\n\004seed\030\004 \001(\004R\004seed\022\024\n\005" + - "error\030\005 \001(\tR\005error\0223\n\013diagnostics\030\006 \003(\0132" + - "\021.sysml.DiagnosticR\013diagnostics\022;\n\016failu" + - "re_reason\030\007 \001(\0162\024.sysml.FailureReasonR\rf" + - "ailureReason\022-\n\tinstances\030\010 \003(\0132\017.sysml." + - "InstanceR\tinstances\"\214\001\n\027RunDocumentQuery" + - "Request\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash\022\031" + - "\n\010query_id\030\002 \001(\tR\007queryId\0227\n\010bindings\030\003 " + - "\003(\0132\033.sysml.DocumentQueryBindingR\010bindin" + - "gs\"b\n\024DocumentQueryBinding\022\034\n\tparameter\030" + - "\001 \001(\tR\tparameter\022,\n\006values\030\002 \003(\0132\024.sysml" + - ".DocumentValueR\006values\"\256\002\n\rDocumentValue" + - "\022\037\n\nelement_id\030\001 \001(\tH\000R\telementId\022#\n\014str" + - "ing_value\030\002 \001(\tH\000R\013stringValue\022\035\n\tint_va" + - "lue\030\003 \001(\003H\000R\010intValue\022\037\n\nreal_value\030\004 \001(" + - "\001H\000R\trealValue\022\037\n\nbool_value\030\005 \001(\010H\000R\tbo" + - "olValue\022\034\n\010infinity\030\006 \001(\010H\000R\010infinity\022-\n" + - "\010quantity\030\010 \001(\0132\017.sysml.QuantityH\000R\010quan" + - "tity\022!\n\014element_type\030\007 \001(\tR\013elementTypeB" + - "\006\n\004kind\")\n\023DocumentQueryColumn\022\022\n\004name\030\001" + - " \001(\tR\004name\"A\n\021DocumentQueryCell\022,\n\006value" + - "s\030\001 \003(\0132\024.sysml.DocumentValueR\006values\"r\n" + - "\020DocumentQueryRow\022.\n\007element\030\001 \001(\0132\024.sys" + - "ml.DocumentValueR\007element\022.\n\005cells\030\002 \003(\013" + - "2\030.sysml.DocumentQueryCellR\005cells\"}\n\030Run" + - "DocumentQueryResponse\0224\n\007columns\030\001 \003(\0132\032" + - ".sysml.DocumentQueryColumnR\007columns\022+\n\004r" + - "ows\030\002 \003(\0132\027.sysml.DocumentQueryRowR\004rows" + - "\"W\n\025RenderDocumentRequest\022\035\n\nmodel_hash\030" + - "\001 \001(\tR\tmodelHash\022\037\n\013document_id\030\002 \001(\tR\nd" + - "ocumentId\"4\n\026RenderDocumentResponse\022\032\n\010m" + - "arkdown\030\001 \001(\tR\010markdown*\223\001\n\rFailureReaso" + - "n\022\036\n\032FAILURE_REASON_UNSPECIFIED\020\000\022\035\n\031FAI" + - "LURE_REASON_EVALUATION\020\001\022\035\n\031FAILURE_REAS" + - "ON_WRONG_KIND\020\002\022$\n FAILURE_REASON_AMBIGU" + - "OUS_SUBJECT\020\003*\235\004\n\013EditFailure\022\034\n\030EDIT_FA" + - "ILURE_UNSPECIFIED\020\000\022\036\n\032EDIT_FAILURE_NO_O" + - "PERATIONS\020\001\022\037\n\033EDIT_FAILURE_UNKNOWN_TARG" + - "ET\020\002\022!\n\035EDIT_FAILURE_AMBIGUOUS_TARGET\020\003\022" + - "\033\n\027EDIT_FAILURE_NOT_VALUED\020\004\022\036\n\032EDIT_FAI" + - "LURE_INVALID_VALUE\020\005\022\035\n\031EDIT_FAILURE_INV" + - "ALID_NAME\020\006\022\032\n\026EDIT_FAILURE_NOT_NAMED\020\007\022" + - "\"\n\036EDIT_FAILURE_RENAME_REFERENCED\020\010\022\"\n\036E" + - "DIT_FAILURE_OVERLAPPING_EDITS\020\t\022\037\n\033EDIT_" + - "FAILURE_RESULT_INVALID\020\n\022\036\n\032EDIT_FAILURE" + - "_OWNER_UNKNOWN\020\013\022$\n EDIT_FAILURE_OWNER_N" + - "OT_NAMESPACE\020\014\022\035\n\031EDIT_FAILURE_ILLEGAL_K" + - "IND\020\r\022\"\n\036EDIT_FAILURE_MEMBER_NAME_TAKEN\020" + - "\016\022\"\n\036EDIT_FAILURE_DELETE_REFERENCED\020\017*\222\001" + - "\n\021PrimitiveOperator\022\"\n\036PRIMITIVE_OPERATO" + - "R_UNSPECIFIED\020\000\022\034\n\030PRIMITIVE_OPERATOR_EQ" + - "UAL\020\001\022\036\n\032PRIMITIVE_OPERATOR_GREATER\020\002\022\033\n" + - "\027PRIMITIVE_OPERATOR_LESS\020\003*n\n\021CompositeO" + - "perator\022\"\n\036COMPOSITE_OPERATOR_UNSPECIFIE" + - "D\020\000\022\032\n\026COMPOSITE_OPERATOR_AND\020\001\022\031\n\025COMPO" + - "SITE_OPERATOR_OR\020\0022\244\013\n\014SysMLService\022D\n\rG" + - "etServerInfo\022\030.sysml.ServerInfoRequest\032\031" + - ".sysml.ServerInfoResponse\022>\n\tParseFile\022\027" + - ".sysml.ParseFileRequest\032\030.sysml.ParseFil" + - "eResponse\022G\n\014ParseSources\022\032.sysml.ParseS" + - "ourcesRequest\032\033.sysml.ParseSourcesRespon" + - "se\022;\n\tGetSymbol\022\027.sysml.GetSymbolRequest" + - "\032\025.sysml.SymbolResponse\022G\n\016GetDiagnostic" + - "s\022\031.sysml.DiagnosticsRequest\032\032.sysml.Dia" + - "gnosticsResponse\022;\n\010Evaluate\022\026.sysml.Eva" + - "luateRequest\032\027.sysml.EvaluateResponse\022D\n" + - "\013Instantiate\022\031.sysml.InstantiateRequest\032" + - "\032.sysml.InstantiateResponse\022J\n\rExecuteAc" + - "tion\022\033.sysml.ExecuteActionRequest\032\034.sysm" + - "l.ExecuteActionResponse\022G\n\014ExecuteState\022" + - "\032.sysml.ExecuteStateRequest\032\033.sysml.Exec" + - "uteStateResponse\0228\n\007Convert\022\025.sysml.Conv" + - "ertRequest\032\026.sysml.ConvertResponse\022A\n\nAp" + - "plyEdits\022\030.sysml.ApplyEditsRequest\032\031.sys" + - "ml.ApplyEditsResponse\022S\n\020VerifyConstrain" + - "t\022\036.sysml.VerifyConstraintRequest\032\037.sysm" + - "l.VerifyConstraintResponse\022V\n\021VerifyRequ" + - "irement\022\037.sysml.VerifyRequirementRequest" + - "\032 .sysml.VerifyRequirementResponse\022Y\n\022Ve" + - "rifySatisfaction\022 .sysml.VerifySatisfact" + - "ionRequest\032!.sysml.VerifySatisfactionRes" + - "ponse\022G\n\014EvaluateCalc\022\032.sysml.EvaluateCa" + - "lcRequest\032\033.sysml.EvaluateCalcResponse\022D" + - "\n\013RunAnalysis\022\031.sysml.RunAnalysisRequest" + - "\032\032.sysml.RunAnalysisResponse\022;\n\010RunSweep" + - "\022\026.sysml.RunSweepRequest\032\027.sysml.RunSwee" + - "pResponse\0222\n\005Query\022\023.sysml.QueryRequest\032" + - "\024.sysml.QueryResponse\022S\n\020RunDocumentQuer" + - "y\022\036.sysml.RunDocumentQueryRequest\032\037.sysm" + - "l.RunDocumentQueryResponse\022M\n\016RenderDocu" + - "ment\022\034.sysml.RenderDocumentRequest\032\035.sys" + - "ml.RenderDocumentResponseBJ\n\034org.openmbe", - "e.opensysml.protoP\001Z(github.com/Open-MBE" + - "E/OpenSysML/api/protob\006proto3" + "entRefH\000R\016measurementRef\022\034\n\010infinity\030\020 \001" + + "(\010H\000R\010infinityB\006\n\004kind\"Q\n\005Array\022\036\n\ndimen" + + "sions\030\001 \003(\003R\ndimensions\022(\n\010elements\030\002 \003(" + + "\0132\014.sysml.ValueR\010elements\"6\n\006Vector\022,\n\nc" + + "omponents\030\001 \003(\0132\014.sysml.ValueR\ncomponent" + + "s\"A\n\016VectorQuantity\022/\n\ncomponents\030\001 \003(\0132" + + "\017.sysml.QuantityR\ncomponents\";\n\007Complex\022" + + "\022\n\004real\030\001 \001(\001R\004real\022\034\n\timaginary\030\002 \001(\001R\t" + + "imaginary\"g\n\013EnumLiteral\022\035\n\nliteral_id\030\001" + + " \001(\tR\tliteralId\022%\n\016enumeration_id\030\002 \001(\tR" + + "\renumerationId\022\022\n\004name\030\003 \001(\tR\004name\"9\n\rVa" + + "lueSequence\022(\n\010elements\030\001 \003(\0132\014.sysml.Va" + + "lueR\010elements\"\251\001\n\010Quantity\022%\n\rint_magnit" + + "ude\030\001 \001(\003H\000R\014intMagnitude\022\'\n\016real_magnit" + + "ude\030\002 \001(\001H\000R\rrealMagnitude\022\022\n\004unit\030\003 \001(\t" + + "R\004unit\022,\n\tunit_term\030\004 \001(\0132\017.sysml.UnitTe" + + "rmR\010unitTermB\013\n\tmagnitude\"k\n\016Measurement" + + "Ref\022\022\n\004unit\030\001 \001(\tR\004unit\022,\n\tunit_term\030\002 \001" + + "(\0132\017.sysml.UnitTermR\010unitTerm\022\027\n\007unit_id" + + "\030\003 \001(\tR\006unitId\"q\n\010UnitTerm\022\033\n\tscale_num\030" + + "\001 \001(\001R\010scaleNum\022\033\n\tscale_den\030\002 \001(\001R\010scal" + + "eDen\022+\n\007factors\030\003 \003(\0132\021.sysml.UnitFactor" + + "R\007factors\"A\n\nUnitFactor\022\027\n\007unit_id\030\001 \001(\t" + + "R\006unitId\022\032\n\010exponent\030\002 \001(\001R\010exponent\"c\n\n" + + "Diagnostic\022\032\n\010severity\030\001 \001(\tR\010severity\022\030" + + "\n\007message\030\002 \001(\tR\007message\022\037\n\004span\030\003 \001(\0132\013" + + ".sysml.SpanR\004span\"\212\001\n\004Span\022\022\n\004file\030\001 \001(\t" + + "R\004file\022\035\n\nstart_line\030\002 \001(\005R\tstartLine\022\033\n" + + "\tstart_col\030\003 \001(\005R\010startCol\022\031\n\010end_line\030\004" + + " \001(\005R\007endLine\022\027\n\007end_col\030\005 \001(\005R\006endCol\"\023" + + "\n\021ServerInfoRequest\"R\n\022ServerInfoRespons" + + "e\022\030\n\007version\030\001 \001(\tR\007version\022\"\n\014capabilit" + + "ies\030\002 \003(\tR\014capabilities\"p\n\014QueryRequest\022" + + "\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash\022\"\n\005query\030" + + "\002 \001(\0132\014.sysml.QueryR\005query\022\035\n\noslc_query" + + "\030\003 \001(\tR\toslcQuery\"F\n\rQueryResponse\0225\n\010el" + + "ements\030\001 \003(\0132\031.sysml.QueryResultElementR" + + "\010elements\"^\n\005Query\022\024\n\005scope\030\001 \003(\tR\005scope" + + "\022\026\n\006select\030\002 \003(\tR\006select\022\'\n\005where\030\003 \001(\0132" + + "\021.sysml.ConstraintR\005where\"\222\001\n\nConstraint" + + "\022:\n\tprimitive\030\001 \001(\0132\032.sysml.PrimitiveCon" + + "straintH\000R\tprimitive\022:\n\tcomposite\030\002 \001(\0132" + + "\032.sysml.CompositeConstraintH\000R\tcomposite" + + "B\014\n\nconstraint\"\227\001\n\023PrimitiveConstraint\022\030" + + "\n\007inverse\030\001 \001(\010R\007inverse\022\032\n\010property\030\002 \001" + + "(\tR\010property\0224\n\010operator\030\003 \001(\0162\030.sysml.P" + + "rimitiveOperatorR\010operator\022\024\n\005value\030\004 \003(" + + "\tR\005value\"~\n\023CompositeConstraint\0224\n\010opera" + + "tor\030\001 \001(\0162\030.sysml.CompositeOperatorR\010ope" + + "rator\0221\n\nconstraint\030\002 \003(\0132\021.sysml.Constr" + + "aintR\nconstraint\"\302\001\n\022QueryResultElement\022" + + "\016\n\002id\030\001 \001(\tR\002id\022\022\n\004type\030\002 \001(\tR\004type\022I\n\np" + + "roperties\030\003 \003(\0132).sysml.QueryResultEleme" + + "nt.PropertiesEntryR\nproperties\032=\n\017Proper" + + "tiesEntry\022\020\n\003key\030\001 \001(\tR\003key\022\024\n\005value\030\002 \001" + + "(\tR\005value:\0028\001\"\220\001\n\nSweepRange\022\034\n\tparamete" + + "r\030\001 \001(\tR\tparameter\022\"\n\005start\030\002 \001(\0132\014.sysm" + + "l.ValueR\005start\022\036\n\003end\030\003 \001(\0132\014.sysml.Valu" + + "eR\003end\022 \n\004step\030\004 \001(\0132\014.sysml.ValueR\004step" + + "\"\244\003\n\017RunSweepRequest\022\035\n\nmodel_hash\030\001 \001(\t" + + "R\tmodelHash\022\033\n\tsymbol_id\030\002 \001(\tR\010symbolId" + + "\022*\n\021subject_symbol_id\030\003 \001(\tR\017subjectSymb" + + "olId\022*\n\targuments\030\004 \003(\0132\014.sysml.ValueR\ta" + + "rguments\022S\n\017named_arguments\030\005 \003(\0132*.sysm" + + "l.RunSweepRequest.NamedArgumentsEntryR\016n" + + "amedArguments\022)\n\006ranges\030\006 \003(\0132\021.sysml.Sw" + + "eepRangeR\006ranges\022\030\n\007samples\030\007 \001(\003R\007sampl" + + "es\022\022\n\004seed\030\010 \001(\004R\004seed\032O\n\023NamedArguments" + + "Entry\022\020\n\003key\030\001 \001(\tR\003key\022\"\n\005value\030\002 \001(\0132\014" + + ".sysml.ValueR\005value:\0028\001\"\210\002\n\010SweepRow\022)\n\006" + + "inputs\030\001 \003(\0132\021.sysml.CalcOutputR\006inputs\022" + + "+\n\007outputs\030\002 \003(\0132\021.sysml.CalcOutputR\007out" + + "puts\022*\n\010verdicts\030\003 \003(\0132\016.sysml.VerdictR\010" + + "verdicts\022%\n\016elapsed_micros\030\004 \001(\003R\relapse" + + "dMicros\022\024\n\005error\030\005 \001(\tR\005error\022;\n\016failure" + + "_reason\030\006 \001(\0162\024.sysml.FailureReasonR\rfai" + + "lureReason\"\274\002\n\020RunSweepResponse\022#\n\004rows\030" + + "\001 \003(\0132\017.sysml.SweepRowR\004rows\022\036\n\nparamete" + + "rs\030\002 \003(\tR\nparameters\022\030\n\007sampled\030\003 \001(\010R\007s" + + "ampled\022\022\n\004seed\030\004 \001(\004R\004seed\022\024\n\005error\030\005 \001(" + + "\tR\005error\0223\n\013diagnostics\030\006 \003(\0132\021.sysml.Di" + + "agnosticR\013diagnostics\022;\n\016failure_reason\030" + + "\007 \001(\0162\024.sysml.FailureReasonR\rfailureReas" + + "on\022-\n\tinstances\030\010 \003(\0132\017.sysml.InstanceR\t" + + "instances\"\214\001\n\027RunDocumentQueryRequest\022\035\n" + + "\nmodel_hash\030\001 \001(\tR\tmodelHash\022\031\n\010query_id" + + "\030\002 \001(\tR\007queryId\0227\n\010bindings\030\003 \003(\0132\033.sysm" + + "l.DocumentQueryBindingR\010bindings\"b\n\024Docu" + + "mentQueryBinding\022\034\n\tparameter\030\001 \001(\tR\tpar" + + "ameter\022,\n\006values\030\002 \003(\0132\024.sysml.DocumentV" + + "alueR\006values\"\256\002\n\rDocumentValue\022\037\n\nelemen" + + "t_id\030\001 \001(\tH\000R\telementId\022#\n\014string_value\030" + + "\002 \001(\tH\000R\013stringValue\022\035\n\tint_value\030\003 \001(\003H" + + "\000R\010intValue\022\037\n\nreal_value\030\004 \001(\001H\000R\trealV" + + "alue\022\037\n\nbool_value\030\005 \001(\010H\000R\tboolValue\022\034\n" + + "\010infinity\030\006 \001(\010H\000R\010infinity\022-\n\010quantity\030" + + "\010 \001(\0132\017.sysml.QuantityH\000R\010quantity\022!\n\014el" + + "ement_type\030\007 \001(\tR\013elementTypeB\006\n\004kind\")\n" + + "\023DocumentQueryColumn\022\022\n\004name\030\001 \001(\tR\004name" + + "\"A\n\021DocumentQueryCell\022,\n\006values\030\001 \003(\0132\024." + + "sysml.DocumentValueR\006values\"r\n\020DocumentQ" + + "ueryRow\022.\n\007element\030\001 \001(\0132\024.sysml.Documen" + + "tValueR\007element\022.\n\005cells\030\002 \003(\0132\030.sysml.D" + + "ocumentQueryCellR\005cells\"}\n\030RunDocumentQu" + + "eryResponse\0224\n\007columns\030\001 \003(\0132\032.sysml.Doc" + + "umentQueryColumnR\007columns\022+\n\004rows\030\002 \003(\0132" + + "\027.sysml.DocumentQueryRowR\004rows\"W\n\025Render" + + "DocumentRequest\022\035\n\nmodel_hash\030\001 \001(\tR\tmod" + + "elHash\022\037\n\013document_id\030\002 \001(\tR\ndocumentId\"" + + "4\n\026RenderDocumentResponse\022\032\n\010markdown\030\001 " + + "\001(\tR\010markdown*\223\001\n\rFailureReason\022\036\n\032FAILU" + + "RE_REASON_UNSPECIFIED\020\000\022\035\n\031FAILURE_REASO" + + "N_EVALUATION\020\001\022\035\n\031FAILURE_REASON_WRONG_K" + + "IND\020\002\022$\n FAILURE_REASON_AMBIGUOUS_SUBJEC" + + "T\020\003*\235\004\n\013EditFailure\022\034\n\030EDIT_FAILURE_UNSP" + + "ECIFIED\020\000\022\036\n\032EDIT_FAILURE_NO_OPERATIONS\020" + + "\001\022\037\n\033EDIT_FAILURE_UNKNOWN_TARGET\020\002\022!\n\035ED" + + "IT_FAILURE_AMBIGUOUS_TARGET\020\003\022\033\n\027EDIT_FA" + + "ILURE_NOT_VALUED\020\004\022\036\n\032EDIT_FAILURE_INVAL" + + "ID_VALUE\020\005\022\035\n\031EDIT_FAILURE_INVALID_NAME\020" + + "\006\022\032\n\026EDIT_FAILURE_NOT_NAMED\020\007\022\"\n\036EDIT_FA" + + "ILURE_RENAME_REFERENCED\020\010\022\"\n\036EDIT_FAILUR" + + "E_OVERLAPPING_EDITS\020\t\022\037\n\033EDIT_FAILURE_RE" + + "SULT_INVALID\020\n\022\036\n\032EDIT_FAILURE_OWNER_UNK" + + "NOWN\020\013\022$\n EDIT_FAILURE_OWNER_NOT_NAMESPA" + + "CE\020\014\022\035\n\031EDIT_FAILURE_ILLEGAL_KIND\020\r\022\"\n\036E" + + "DIT_FAILURE_MEMBER_NAME_TAKEN\020\016\022\"\n\036EDIT_" + + "FAILURE_DELETE_REFERENCED\020\017*\222\001\n\021Primitiv" + + "eOperator\022\"\n\036PRIMITIVE_OPERATOR_UNSPECIF" + + "IED\020\000\022\034\n\030PRIMITIVE_OPERATOR_EQUAL\020\001\022\036\n\032P" + + "RIMITIVE_OPERATOR_GREATER\020\002\022\033\n\027PRIMITIVE" + + "_OPERATOR_LESS\020\003*n\n\021CompositeOperator\022\"\n" + + "\036COMPOSITE_OPERATOR_UNSPECIFIED\020\000\022\032\n\026COM" + + "POSITE_OPERATOR_AND\020\001\022\031\n\025COMPOSITE_OPERA" + + "TOR_OR\020\0022\244\013\n\014SysMLService\022D\n\rGetServerIn" + + "fo\022\030.sysml.ServerInfoRequest\032\031.sysml.Ser" + + "verInfoResponse\022>\n\tParseFile\022\027.sysml.Par" + + "seFileRequest\032\030.sysml.ParseFileResponse\022" + + "G\n\014ParseSources\022\032.sysml.ParseSourcesRequ" + + "est\032\033.sysml.ParseSourcesResponse\022;\n\tGetS" + + "ymbol\022\027.sysml.GetSymbolRequest\032\025.sysml.S" + + "ymbolResponse\022G\n\016GetDiagnostics\022\031.sysml." + + "DiagnosticsRequest\032\032.sysml.DiagnosticsRe" + + "sponse\022;\n\010Evaluate\022\026.sysml.EvaluateReque" + + "st\032\027.sysml.EvaluateResponse\022D\n\013Instantia" + + "te\022\031.sysml.InstantiateRequest\032\032.sysml.In" + + "stantiateResponse\022J\n\rExecuteAction\022\033.sys" + + "ml.ExecuteActionRequest\032\034.sysml.ExecuteA" + + "ctionResponse\022G\n\014ExecuteState\022\032.sysml.Ex" + + "ecuteStateRequest\032\033.sysml.ExecuteStateRe" + + "sponse\0228\n\007Convert\022\025.sysml.ConvertRequest" + + "\032\026.sysml.ConvertResponse\022A\n\nApplyEdits\022\030" + + ".sysml.ApplyEditsRequest\032\031.sysml.ApplyEd" + + "itsResponse\022S\n\020VerifyConstraint\022\036.sysml." + + "VerifyConstraintRequest\032\037.sysml.VerifyCo" + + "nstraintResponse\022V\n\021VerifyRequirement\022\037." + + "sysml.VerifyRequirementRequest\032 .sysml.V" + + "erifyRequirementResponse\022Y\n\022VerifySatisf" + + "action\022 .sysml.VerifySatisfactionRequest" + + "\032!.sysml.VerifySatisfactionResponse\022G\n\014E" + + "valuateCalc\022\032.sysml.EvaluateCalcRequest\032" + + "\033.sysml.EvaluateCalcResponse\022D\n\013RunAnaly" + + "sis\022\031.sysml.RunAnalysisRequest\032\032.sysml.R" + + "unAnalysisResponse\022;\n\010RunSweep\022\026.sysml.R" + + "unSweepRequest\032\027.sysml.RunSweepResponse\022" + + "2\n\005Query\022\023.sysml.QueryRequest\032\024.sysml.Qu" + + "eryResponse\022S\n\020RunDocumentQuery\022\036.sysml." + + "RunDocumentQueryRequest\032\037.sysml.RunDocum" + + "entQueryResponse\022M\n\016RenderDocument\022\034.sys" + + "ml.RenderDocumentRequest\032\035.sysml.RenderD", + "ocumentResponseBJ\n\034org.openmbee.opensysm" + + "l.protoP\001Z(github.com/Open-MBEE/OpenSysM" + + "L/api/protob\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -1215,7 +1216,7 @@ public static void registerAllExtensions( internal_static_sysml_Value_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_sysml_Value_descriptor, - new java.lang.String[] { "IntValue", "RealValue", "BoolValue", "StringValue", "InstanceId", "Sequence", "Null", "Quantity", "EnumLiteral", "Unset", "Complex", "Array", "Vector", "VectorQuantity", "MeasurementRef", "Kind", }); + new java.lang.String[] { "IntValue", "RealValue", "BoolValue", "StringValue", "InstanceId", "Sequence", "Null", "Quantity", "EnumLiteral", "Unset", "Complex", "Array", "Vector", "VectorQuantity", "MeasurementRef", "Infinity", "Kind", }); internal_static_sysml_Array_descriptor = getDescriptor().getMessageType(48); internal_static_sysml_Array_fieldAccessorTable = new diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Value.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Value.java index 1aee10580..78aec21c3 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Value.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Value.java @@ -68,6 +68,7 @@ public enum KindCase VECTOR(13), VECTOR_QUANTITY(14), MEASUREMENT_REF(15), + INFINITY(16), KIND_NOT_SET(0); private final int value; private KindCase(int value) { @@ -100,6 +101,7 @@ public static KindCase forNumber(int value) { case 13: return VECTOR; case 14: return VECTOR_QUANTITY; case 15: return MEASUREMENT_REF; + case 16: return INFINITY; case 0: return KIND_NOT_SET; default: return null; } @@ -674,6 +676,39 @@ public org.openmbee.opensysml.proto.MeasurementRefOrBuilder getMeasurementRefOrB return org.openmbee.opensysml.proto.MeasurementRef.getDefaultInstance(); } + public static final int INFINITY_FIELD_NUMBER = 16; + /** + *

+   * The unbounded value `*`, which is no number and no string: ordered above
+   * every finite magnitude and refused by arithmetic. Always true when set,
+   * as DocumentValue.infinity is.
+   * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return Whether the infinity field is set. + */ + @java.lang.Override + public boolean hasInfinity() { + return kindCase_ == 16; + } + /** + *
+   * The unbounded value `*`, which is no number and no string: ordered above
+   * every finite magnitude and refused by arithmetic. Always true when set,
+   * as DocumentValue.infinity is.
+   * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return The infinity. + */ + @java.lang.Override + public boolean getInfinity() { + if (kindCase_ == 16) { + return (java.lang.Boolean) kind_; + } + return false; + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -738,6 +773,10 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (kindCase_ == 15) { output.writeMessage(15, (org.openmbee.opensysml.proto.MeasurementRef) kind_); } + if (kindCase_ == 16) { + output.writeBool( + 16, (boolean)((java.lang.Boolean) kind_)); + } getUnknownFields().writeTo(output); } @@ -810,6 +849,11 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(15, (org.openmbee.opensysml.proto.MeasurementRef) kind_); } + if (kindCase_ == 16) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize( + 16, (boolean)((java.lang.Boolean) kind_)); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -888,6 +932,10 @@ public boolean equals(final java.lang.Object obj) { if (!getMeasurementRef() .equals(other.getMeasurementRef())) return false; break; + case 16: + if (getInfinity() + != other.getInfinity()) return false; + break; case 0: default: } @@ -968,6 +1016,11 @@ public int hashCode() { hash = (37 * hash) + MEASUREMENT_REF_FIELD_NUMBER; hash = (53 * hash) + getMeasurementRef().hashCode(); break; + case 16: + hash = (37 * hash) + INFINITY_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getInfinity()); + break; case 0: default: } @@ -1282,6 +1335,10 @@ public Builder mergeFrom(org.openmbee.opensysml.proto.Value other) { mergeMeasurementRef(other.getMeasurementRef()); break; } + case INFINITY: { + setInfinity(other.getInfinity()); + break; + } case KIND_NOT_SET: { break; } @@ -1405,6 +1462,11 @@ public Builder mergeFrom( kindCase_ = 15; break; } // case 122 + case 128: { + kind_ = input.readBool(); + kindCase_ = 16; + break; + } // case 128 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -3245,6 +3307,72 @@ public org.openmbee.opensysml.proto.MeasurementRefOrBuilder getMeasurementRefOrB return measurementRefBuilder_; } + /** + *
+     * The unbounded value `*`, which is no number and no string: ordered above
+     * every finite magnitude and refused by arithmetic. Always true when set,
+     * as DocumentValue.infinity is.
+     * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return Whether the infinity field is set. + */ + public boolean hasInfinity() { + return kindCase_ == 16; + } + /** + *
+     * The unbounded value `*`, which is no number and no string: ordered above
+     * every finite magnitude and refused by arithmetic. Always true when set,
+     * as DocumentValue.infinity is.
+     * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return The infinity. + */ + public boolean getInfinity() { + if (kindCase_ == 16) { + return (java.lang.Boolean) kind_; + } + return false; + } + /** + *
+     * The unbounded value `*`, which is no number and no string: ordered above
+     * every finite magnitude and refused by arithmetic. Always true when set,
+     * as DocumentValue.infinity is.
+     * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @param value The infinity to set. + * @return This builder for chaining. + */ + public Builder setInfinity(boolean value) { + + kindCase_ = 16; + kind_ = value; + onChanged(); + return this; + } + /** + *
+     * The unbounded value `*`, which is no number and no string: ordered above
+     * every finite magnitude and refused by arithmetic. Always true when set,
+     * as DocumentValue.infinity is.
+     * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return This builder for chaining. + */ + public Builder clearInfinity() { + if (kindCase_ == 16) { + kindCase_ = 0; + kind_ = null; + onChanged(); + } + return this; + } + // @@protoc_insertion_point(builder_scope:sysml.Value) } diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ValueOrBuilder.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ValueOrBuilder.java index 2f61dd66a..82dc6529d 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ValueOrBuilder.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ValueOrBuilder.java @@ -321,5 +321,28 @@ public interface ValueOrBuilder extends */ org.openmbee.opensysml.proto.MeasurementRefOrBuilder getMeasurementRefOrBuilder(); + /** + *
+   * The unbounded value `*`, which is no number and no string: ordered above
+   * every finite magnitude and refused by arithmetic. Always true when set,
+   * as DocumentValue.infinity is.
+   * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return Whether the infinity field is set. + */ + boolean hasInfinity(); + /** + *
+   * The unbounded value `*`, which is no number and no string: ordered above
+   * every finite magnitude and refused by arithmetic. Always true when set,
+   * as DocumentValue.infinity is.
+   * 
+ * + * bool infinity = 16 [json_name = "infinity"]; + * @return The infinity. + */ + boolean getInfinity(); + org.openmbee.opensysml.proto.Value.KindCase getKindCase(); } diff --git a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/internal/ProtosTest.java b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/internal/ProtosTest.java index 8c0744413..ca9629e01 100644 --- a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/internal/ProtosTest.java +++ b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/internal/ProtosTest.java @@ -466,4 +466,21 @@ void anInstanceReadsItsFeatureValuesWholeAndImmutably() { assertTrue(mass.materialized()); assertEquals(Optional.empty(), mass.error()); } + + @Test + void onlyAnAssertedInfinityArmIsTheUnboundedValue() { + org.openmbee.opensysml.proto.Value asserted = + org.openmbee.opensysml.proto.Value.newBuilder().setInfinity(true).build(); + assertEquals(Optional.of(new Value.InfinityValue()), Protos.value(asserted)); + + org.openmbee.opensysml.proto.Value denied = + org.openmbee.opensysml.proto.Value.newBuilder().setInfinity(false).build(); + assertThrows(TransportException.class, () -> Protos.value(denied)); + + org.openmbee.opensysml.proto.Value nested = + org.openmbee.opensysml.proto.Value.newBuilder() + .setSequence(ValueSequence.newBuilder().addElements(denied)) + .build(); + assertThrows(TransportException.class, () -> Protos.value(nested)); + } } diff --git a/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java b/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java index ca155cd16..4ab23f099 100644 --- a/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java +++ b/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java @@ -59,6 +59,8 @@ static org.openmbee.opensysml.proto.Value value(Value value) { builder.setNull(""); } else if (value instanceof Value.UnsetValue) { builder.setUnset(true); + } else if (value instanceof Value.InfinityValue) { + builder.setInfinity(true); } else if (value instanceof Value.QuantityValue quantity) { builder.setQuantity(quantity(quantity.quantity())); } else if (value instanceof Value.EnumerationValue literal) { diff --git a/clients/node/src/core/capabilities.ts b/clients/node/src/core/capabilities.ts index a7f572ce5..fb65578a7 100644 --- a/clients/node/src/core/capabilities.ts +++ b/clients/node/src/core/capabilities.ts @@ -22,6 +22,8 @@ export const CAPABILITY_COMPLEX_VALUES = "complex_values"; export const CAPABILITY_STRUCTURED_VALUES = "structured_values"; /** A bare measurement unit (`SI::m`, `m / s`) as `Value.measurement_ref`, rather than an unsupported null. */ export const CAPABILITY_MEASUREMENT_REFS = "measurement_refs"; +/** The unbounded value `*` as `Value.infinity`, rather than an unsupported null. */ +export const CAPABILITY_INFINITY_VALUE = "infinity_value"; /** `ParseFileRequest.language`, which declares the language of inline content. */ export const CAPABILITY_INLINE_LANGUAGE = "inline_language"; /** `ParseFileRequest.strict_conformance`. */ diff --git a/clients/node/src/core/index.ts b/clients/node/src/core/index.ts index 0727025c3..7ecdae194 100644 --- a/clients/node/src/core/index.ts +++ b/clients/node/src/core/index.ts @@ -28,6 +28,7 @@ export { CAPABILITY_ENUM_VALUES, CAPABILITY_EVALUATE_SUBJECT, CAPABILITY_FEATURE_VALUES, + CAPABILITY_INFINITY_VALUE, CAPABILITY_INLINE_LANGUAGE, CAPABILITY_MEASUREMENT_REFS, CAPABILITY_QUERY, diff --git a/clients/node/src/core/values.ts b/clients/node/src/core/values.ts index 1c748eb28..e1a84e1e6 100644 --- a/clients/node/src/core/values.ts +++ b/clients/node/src/core/values.ts @@ -109,6 +109,7 @@ export type SysMLValue = | { kind: "vectorQuantity"; components: QuantityValue[] } | { kind: "null"; reason: string } | { kind: "unset" } + | { kind: "infinity" } | { kind: "absent" }; /** What a verification answered about. Kept for the verification RPCs of a later version. */ @@ -178,6 +179,12 @@ export function decodeValue(value: Value | undefined): SysMLValue { return { kind: "null", reason: kind.value }; case "unset": return { kind: "unset" }; + case "infinity": + // Only an asserted arm carries the unbounded value. + if (!kind.value) { + throw new MalformedValueError("the infinity arm states no value unless it is true"); + } + return { kind: "infinity" }; case undefined: return { kind: "absent" }; } @@ -255,6 +262,8 @@ export function encodeValue(value: SysMLValue): Value { return create(ValueSchema, { kind: { case: "null", value: value.reason } }); case "unset": return create(ValueSchema, { kind: { case: "unset", value: true } }); + case "infinity": + return create(ValueSchema, { kind: { case: "infinity", value: true } }); case "absent": throw new MalformedValueError("an absent value is no value at all, so it cannot be sent"); } @@ -331,6 +340,8 @@ export function formatValue(value: SysMLValue): string { return value.reason === "" ? "null" : `null (${value.reason})`; case "unset": return "unset"; + case "infinity": + return "*"; case "absent": return "absent"; } diff --git a/clients/node/src/generated/sysml_pb.ts b/clients/node/src/generated/sysml_pb.ts index 8880c3111..1fbafc31f 100644 --- a/clients/node/src/generated/sysml_pb.ts +++ b/clients/node/src/generated/sysml_pb.ts @@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file sysml.proto. */ export const file_sysml: GenFile = /*@__PURE__*/ - fileDesc("CgtzeXNtbC5wcm90bxIFc3lzbWwi4gEKB1ZlcmRpY3QSDAoEa2luZBgBIAEoCRISCgplbGVtZW50X2lkGAIgASgJEg8KB2VsZW1lbnQYAyABKAkSDQoFaG9sZHMYBCABKAgSEQoJY29uZGl0aW9uGAUgASgJEhMKC2luc3RhbmNlX2lkGAYgASgDEhgKEGluc3RhbmNlX3R5cGVfaWQYByABKAkSDQoFZXJyb3IYCCABKAkSLAoOZmFpbHVyZV9yZWFzb24YCSABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uEhYKDnJlcXVpcmVtZW50X2lkGAogASgJIlsKF1ZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJEhkKEXN1YmplY3Rfc3ltYm9sX2lkGAMgASgJIpYBChhWZXJpZnlDb25zdHJhaW50UmVzcG9uc2USHwoHdmVyZGljdBgBIAEoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljIlwKGFZlcmlmeVJlcXVpcmVtZW50UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCSJtChNWZXJpZmljYXRpb25WZXJkaWN0Eg8KB2Nhc2VfaWQYASABKAkSDAoEa2luZBgCIAEoCRIOCgZkZXRhaWwYAyABKAkSDwoHc3ViY2FzZRgEIAEoCBIWCg5yZXF1aXJlbWVudF9pZBgFIAEoCSLSAQoZVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRIfCgd2ZXJkaWN0GAEgASgLMg4uc3lzbWwuVmVyZGljdBIiCglpbnN0YW5jZXMYAiADKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgDIAEoCRImCgtkaWFnbm9zdGljcxgEIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSOQoVdmVyaWZpY2F0aW9uX3ZlcmRpY3RzGAUgAygLMhouc3lzbWwuVmVyaWZpY2F0aW9uVmVyZGljdCJCChlWZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJIoICChpWZXJpZnlTYXRpc2ZhY3Rpb25SZXNwb25zZRIgCgh2ZXJkaWN0cxgBIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAUgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYBiADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0Il0KE0V2YWx1YXRlQ2FsY1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSHwoJYXJndW1lbnRzGAMgAygLMgwuc3lzbWwuVmFsdWUivQEKFEV2YWx1YXRlQ2FsY1Jlc3BvbnNlEhwKBnJlc3VsdBgBIAEoCzIMLnN5c21sLlZhbHVlEiIKB291dHB1dHMYAiADKAsyES5zeXNtbC5DYWxjT3V0cHV0Eg0KBWVycm9yGAMgASgJEiYKC2RpYWdub3N0aWNzGAQgAygLMhEuc3lzbWwuRGlhZ25vc3RpYxIsCg5mYWlsdXJlX3JlYXNvbhgFIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24iNwoKQ2FsY091dHB1dBIMCgRuYW1lGAEgASgJEhsKBXZhbHVlGAIgASgLMgwuc3lzbWwuVmFsdWUihAIKElJ1bkFuYWx5c2lzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCRIfCglhcmd1bWVudHMYBCADKAsyDC5zeXNtbC5WYWx1ZRJGCg9uYW1lZF9hcmd1bWVudHMYBSADKAsyLS5zeXNtbC5SdW5BbmFseXNpc1JlcXVlc3QuTmFtZWRBcmd1bWVudHNFbnRyeRpDChNOYW1lZEFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKfAgoTUnVuQW5hbHlzaXNSZXNwb25zZRIiCgdvdXRwdXRzGAEgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIgCgh2ZXJkaWN0cxgCIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAMgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYBCABKAkSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYByADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0IowBChBQYXJzZUZpbGVSZXF1ZXN0EhMKCWZpbGVfcGF0aBgBIAEoCUgAEhEKB2NvbnRlbnQYAiABKAlIABIYCgxjb250ZW50X2hhc2gYAyABKAlCAhgBEhAKCGxhbmd1YWdlGAQgASgJEhoKEnN0cmljdF9jb25mb3JtYW5jZRgFIAEoCEIICgZzb3VyY2UiYgoOU291cmNlRG9jdW1lbnQSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhAKCGxhbmd1YWdlGAMgASgJEgwKBG5hbWUYBCABKAlCCAoGc291cmNlIlsKE1BhcnNlU291cmNlc1JlcXVlc3QSKAoJZG9jdW1lbnRzGAEgAygLMhUuc3lzbWwuU291cmNlRG9jdW1lbnQSGgoSc3RyaWN0X2NvbmZvcm1hbmNlGAIgASgIIoMBChRQYXJzZVNvdXJjZXNSZXNwb25zZRISCgptb2RlbF9oYXNoGAEgASgJEiAKBXJvb3RzGAIgAygLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkifwoRUGFyc2VGaWxlUmVzcG9uc2USEgoKbW9kZWxfaGFzaBgBIAEoCRIfCgRyb290GAIgASgLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkiOQoQR2V0U3ltYm9sUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCSJCCg5TeW1ib2xSZXNwb25zZRIhCgZzeW1ib2wYASABKAsyES5zeXNtbC5TeW1ib2xJbmZvEg0KBWVycm9yGAIgASgJIigKEkRpYWdub3N0aWNzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJIkwKE0RpYWdub3N0aWNzUmVzcG9uc2USJgoLZGlhZ25vc3RpY3MYASADKAsyES5zeXNtbC5EaWFnbm9zdGljEg0KBWVycm9yGAIgASgJIm8KD0V2YWx1YXRlUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhIKCmV4cHJlc3Npb24YAiABKAkSGQoRY29udGV4dF9zeW1ib2xfaWQYAyABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYBCABKAkiZwoQRXZhbHVhdGVSZXNwb25zZRIcCgZyZXN1bHQYASABKAsyDC5zeXNtbC5WYWx1ZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMiwgEKCEluc3RhbmNlEgoKAmlkGAEgASgDEhYKDnR5cGVfc3ltYm9sX2lkGAIgASgJEjoKDmZlYXR1cmVfdmFsdWVzGAQgAygLMiIuc3lzbWwuSW5zdGFuY2UuRmVhdHVyZVZhbHVlc0VudHJ5GkkKEkZlYXR1cmVWYWx1ZXNFbnRyeRILCgNrZXkYASABKAkSIgoFdmFsdWUYAiABKAsyEy5zeXNtbC5GZWF0dXJlVmFsdWU6AjgBSgQIAxAEUgVzbG90cyKEAQoMRmVhdHVyZVZhbHVlEhQKDGZlYXR1cmVfbmFtZRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlEhwKBnZhbHVlcxgDIAMoCzIMLnN5c21sLlZhbHVlEhQKDG1hdGVyaWFsaXplZBgEIAEoCBINCgVlcnJvchgFIAEoCSI7ChJJbnN0YW50aWF0ZVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkikwEKE0luc3RhbnRpYXRlUmVzcG9uc2USIQoIaW5zdGFuY2UYASABKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSIgoJaW5zdGFuY2VzGAQgAygLMg8uc3lzbWwuSW5zdGFuY2UiugEKFEV4ZWN1dGVBY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGAoQYWN0aW9uX3N5bWJvbF9pZBgCIAEoCRI3CgZpbnB1dHMYAyADKAsyJy5zeXNtbC5FeGVjdXRlQWN0aW9uUmVxdWVzdC5JbnB1dHNFbnRyeRo7CgtJbnB1dHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKFUV4ZWN1dGVBY3Rpb25SZXNwb25zZRI6CgdvdXRwdXRzGAEgAygLMikuc3lzbWwuRXhlY3V0ZUFjdGlvblJlc3BvbnNlLk91dHB1dHNFbnRyeRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMaPAoMT3V0cHV0c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASJaChNFeGVjdXRlU3RhdGVSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSHwoXc3RhdGVfbWFjaGluZV9zeW1ib2xfaWQYAiABKAkSDgoGZXZlbnRzGAMgAygJIu4BChRFeGVjdXRlU3RhdGVSZXNwb25zZRIWCg5zdGF0ZXNfdmlzaXRlZBgBIAMoCRJECg1maW5hbF9jb250ZXh0GAIgAygLMi0uc3lzbWwuRXhlY3V0ZVN0YXRlUmVzcG9uc2UuRmluYWxDb250ZXh0RW50cnkSDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljGkEKEUZpbmFsQ29udGV4dEVudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKgAQoOQ29udmVydFJlcXVlc3QSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhQKCm1vZGVsX2hhc2gYBiABKAlIABITCgtmcm9tX2Zvcm1hdBgDIAEoCRIRCgl0b19mb3JtYXQYBCABKAkSHgoWdG9sZXJhdGVfc3ludGF4X2Vycm9ycxgFIAEoCEIICgZzb3VyY2UitAEKD0NvbnZlcnRSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEhMKC2Zyb21fZm9ybWF0GAIgASgJEhEKCXRvX2Zvcm1hdBgDIAEoCRINCgVlcnJvchgEIAEoCRImCgtkaWFnbm9zdGljcxgFIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSFAoMZXhwZXJpbWVudGFsGAYgASgIEhsKE2V4cGVyaW1lbnRhbF9ub3RpY2UYByABKAkiUQoRQXBwbHlFZGl0c1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIoCgpvcGVyYXRpb25zGAIgAygLMhQuc3lzbWwuRWRpdE9wZXJhdGlvbiK8AQoNRWRpdE9wZXJhdGlvbhIoCglzZXRfdmFsdWUYASABKAsyEy5zeXNtbC5TZXRWYWx1ZUVkaXRIABIjCgZyZW5hbWUYAiABKAsyES5zeXNtbC5SZW5hbWVFZGl0SAASKgoKYWRkX21lbWJlchgDIAEoCzIULnN5c21sLkFkZE1lbWJlckVkaXRIABIjCgZkZWxldGUYBCABKAsyES5zeXNtbC5EZWxldGVFZGl0SABCCwoJb3BlcmF0aW9uIoIBCg1BZGRNZW1iZXJFZGl0Eg0KBW93bmVyGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEbmFtZRgDIAEoCRIMCgR0eXBlGAQgASgJEhQKDG11bHRpcGxpY2l0eRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtzcGVjaWFsaXplcxgHIAMoCSItCgpEZWxldGVFZGl0Eg4KBnRhcmdldBgBIAEoCRIPCgdjYXNjYWRlGAIgASgIIi0KDFNldFZhbHVlRWRpdBIOCgZ0YXJnZXQYASABKAkSDQoFdmFsdWUYAiABKAkiLgoKUmVuYW1lRWRpdBIOCgZ0YXJnZXQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiwgEKEkFwcGx5RWRpdHNSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEiMKB2FwcGxpZWQYAiADKAsyEi5zeXNtbC5BcHBsaWVkRWRpdBINCgVlcnJvchgDIAEoCRIjCgdmYWlsdXJlGAQgASgOMhIuc3lzbWwuRWRpdEZhaWx1cmUSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEhoKEnJlZmVycmluZ19lbGVtZW50cxgGIAMoCSJ6CgtBcHBsaWVkRWRpdBIXCg9vcGVyYXRpb25faW5kZXgYASABKAUSDgoGdGFyZ2V0GAIgASgJEg4KBm9mZnNldBgDIAEoBRIOCgZsZW5ndGgYBCABKAUSEAoIb2xkX3RleHQYBSABKAkSEAoIbmV3X3RleHQYBiABKAki/QIKClN5bWJvbEluZm8SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRraW5kGAMgASgJEjEKCG1ldGFkYXRhGAQgAygLMh8uc3lzbWwuU3ltYm9sSW5mby5NZXRhZGF0YUVudHJ5EhEKCWNoaWxkX2lkcxgFIAMoCRIoCgphdHRyaWJ1dGVzGAYgAygLMhQuc3lzbWwuQXR0cmlidXRlSW5mbxIiCgl0eXBlX2luZm8YByABKAsyDy5zeXNtbC5UeXBlSW5mbxItCgxtdWx0aXBsaWNpdHkYCCABKAsyFy5zeXNtbC5NdWx0aXBsaWNpdHlJbmZvEi4KD3NwZWNpYWxpemF0aW9ucxgJIAMoCzIVLnN5c21sLlNwZWNpYWxpemF0aW9uEiMKG3dpdGhoZWxkX2xpYnJhcnlfYXR0cmlidXRlcxgKIAEoBRovCg1NZXRhZGF0YUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiWAoOU3BlY2lhbGl6YXRpb24SDAoEa2luZBgBIAEoCRIQCghkZWNsYXJlZBgCIAEoCRIRCgl0YXJnZXRfaWQYAyABKAkSEwoLdGFyZ2V0X2tpbmQYBCABKAkilQEKCFR5cGVJbmZvEhAKCGRlY2xhcmVkGAEgASgJEhMKC3Jlc29sdmVkX2lkGAIgASgJEhUKDXJlc29sdmVkX2tpbmQYAyABKAkSEQoJcHJpbWl0aXZlGAQgASgJEhgKEHByaW1pdGl2ZV9zb3VyY2UYBSABKAkSEAoIcXVhbnRpdHkYBiABKAgSDAoEdW5pdBgHIAEoCSIwChBNdWx0aXBsaWNpdHlJbmZvEg0KBWxvd2VyGAEgASgJEg0KBXVwcGVyGAIgASgJIlYKDUF0dHJpYnV0ZUluZm8SDAoEbmFtZRgBIAEoCRIMCgR0eXBlGAIgASgJEhsKBXZhbHVlGAMgASgLMgwuc3lzbWwuVmFsdWUSDAoEdW5pdBgEIAEoCSLiAwoFVmFsdWUSEwoJaW50X3ZhbHVlGAEgASgDSAASFAoKcmVhbF92YWx1ZRgCIAEoAUgAEhQKCmJvb2xfdmFsdWUYAyABKAhIABIWCgxzdHJpbmdfdmFsdWUYBCABKAlIABIVCgtpbnN0YW5jZV9pZBgFIAEoA0gAEigKCHNlcXVlbmNlGAYgASgLMhQuc3lzbWwuVmFsdWVTZXF1ZW5jZUgAEg4KBG51bGwYByABKAlIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASKgoMZW51bV9saXRlcmFsGAkgASgLMhIuc3lzbWwuRW51bUxpdGVyYWxIABIPCgV1bnNldBgKIAEoCEgAEiEKB2NvbXBsZXgYCyABKAsyDi5zeXNtbC5Db21wbGV4SAASHQoFYXJyYXkYDCABKAsyDC5zeXNtbC5BcnJheUgAEh8KBnZlY3RvchgNIAEoCzINLnN5c21sLlZlY3RvckgAEjAKD3ZlY3Rvcl9xdWFudGl0eRgOIAEoCzIVLnN5c21sLlZlY3RvclF1YW50aXR5SAASMAoPbWVhc3VyZW1lbnRfcmVmGA8gASgLMhUuc3lzbWwuTWVhc3VyZW1lbnRSZWZIAEIGCgRraW5kIjsKBUFycmF5EhIKCmRpbWVuc2lvbnMYASADKAMSHgoIZWxlbWVudHMYAiADKAsyDC5zeXNtbC5WYWx1ZSIqCgZWZWN0b3ISIAoKY29tcG9uZW50cxgBIAMoCzIMLnN5c21sLlZhbHVlIjUKDlZlY3RvclF1YW50aXR5EiMKCmNvbXBvbmVudHMYASADKAsyDy5zeXNtbC5RdWFudGl0eSIqCgdDb21wbGV4EgwKBHJlYWwYASABKAESEQoJaW1hZ2luYXJ5GAIgASgBIkcKC0VudW1MaXRlcmFsEhIKCmxpdGVyYWxfaWQYASABKAkSFgoOZW51bWVyYXRpb25faWQYAiABKAkSDAoEbmFtZRgDIAEoCSIvCg1WYWx1ZVNlcXVlbmNlEh4KCGVsZW1lbnRzGAEgAygLMgwuc3lzbWwuVmFsdWUifAoIUXVhbnRpdHkSFwoNaW50X21hZ25pdHVkZRgBIAEoA0gAEhgKDnJlYWxfbWFnbml0dWRlGAIgASgBSAASDAoEdW5pdBgDIAEoCRIiCgl1bml0X3Rlcm0YBCABKAsyDy5zeXNtbC5Vbml0VGVybUILCgltYWduaXR1ZGUiUwoOTWVhc3VyZW1lbnRSZWYSDAoEdW5pdBgBIAEoCRIiCgl1bml0X3Rlcm0YAiABKAsyDy5zeXNtbC5Vbml0VGVybRIPCgd1bml0X2lkGAMgASgJIlQKCFVuaXRUZXJtEhEKCXNjYWxlX251bRgBIAEoARIRCglzY2FsZV9kZW4YAiABKAESIgoHZmFjdG9ycxgDIAMoCzIRLnN5c21sLlVuaXRGYWN0b3IiLwoKVW5pdEZhY3RvchIPCgd1bml0X2lkGAEgASgJEhAKCGV4cG9uZW50GAIgASgBIkoKCkRpYWdub3N0aWMSEAoIc2V2ZXJpdHkYASABKAkSDwoHbWVzc2FnZRgCIAEoCRIZCgRzcGFuGAMgASgLMgsuc3lzbWwuU3BhbiJeCgRTcGFuEgwKBGZpbGUYASABKAkSEgoKc3RhcnRfbGluZRgCIAEoBRIRCglzdGFydF9jb2wYAyABKAUSEAoIZW5kX2xpbmUYBCABKAUSDwoHZW5kX2NvbBgFIAEoBSITChFTZXJ2ZXJJbmZvUmVxdWVzdCI7ChJTZXJ2ZXJJbmZvUmVzcG9uc2USDwoHdmVyc2lvbhgBIAEoCRIUCgxjYXBhYmlsaXRpZXMYAiADKAkiUwoMUXVlcnlSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGwoFcXVlcnkYAiABKAsyDC5zeXNtbC5RdWVyeRISCgpvc2xjX3F1ZXJ5GAMgASgJIjwKDVF1ZXJ5UmVzcG9uc2USKwoIZWxlbWVudHMYASADKAsyGS5zeXNtbC5RdWVyeVJlc3VsdEVsZW1lbnQiSAoFUXVlcnkSDQoFc2NvcGUYASADKAkSDgoGc2VsZWN0GAIgAygJEiAKBXdoZXJlGAMgASgLMhEuc3lzbWwuQ29uc3RyYWludCJ8CgpDb25zdHJhaW50Ei8KCXByaW1pdGl2ZRgBIAEoCzIaLnN5c21sLlByaW1pdGl2ZUNvbnN0cmFpbnRIABIvCgljb21wb3NpdGUYAiABKAsyGi5zeXNtbC5Db21wb3NpdGVDb25zdHJhaW50SABCDAoKY29uc3RyYWludCJzChNQcmltaXRpdmVDb25zdHJhaW50Eg8KB2ludmVyc2UYASABKAgSEAoIcHJvcGVydHkYAiABKAkSKgoIb3BlcmF0b3IYAyABKA4yGC5zeXNtbC5QcmltaXRpdmVPcGVyYXRvchINCgV2YWx1ZRgEIAMoCSJoChNDb21wb3NpdGVDb25zdHJhaW50EioKCG9wZXJhdG9yGAEgASgOMhguc3lzbWwuQ29tcG9zaXRlT3BlcmF0b3ISJQoKY29uc3RyYWludBgCIAMoCzIRLnN5c21sLkNvbnN0cmFpbnQioAEKElF1ZXJ5UmVzdWx0RWxlbWVudBIKCgJpZBgBIAEoCRIMCgR0eXBlGAIgASgJEj0KCnByb3BlcnRpZXMYAyADKAsyKS5zeXNtbC5RdWVyeVJlc3VsdEVsZW1lbnQuUHJvcGVydGllc0VudHJ5GjEKD1Byb3BlcnRpZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBInMKClN3ZWVwUmFuZ2USEQoJcGFyYW1ldGVyGAEgASgJEhsKBXN0YXJ0GAIgASgLMgwuc3lzbWwuVmFsdWUSGQoDZW5kGAMgASgLMgwuc3lzbWwuVmFsdWUSGgoEc3RlcBgEIAEoCzIMLnN5c21sLlZhbHVlIsACCg9SdW5Td2VlcFJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYAyABKAkSHwoJYXJndW1lbnRzGAQgAygLMgwuc3lzbWwuVmFsdWUSQwoPbmFtZWRfYXJndW1lbnRzGAUgAygLMiouc3lzbWwuUnVuU3dlZXBSZXF1ZXN0Lk5hbWVkQXJndW1lbnRzRW50cnkSIQoGcmFuZ2VzGAYgAygLMhEuc3lzbWwuU3dlZXBSYW5nZRIPCgdzYW1wbGVzGAcgASgDEgwKBHNlZWQYCCABKAQaQwoTTmFtZWRBcmd1bWVudHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKCFN3ZWVwUm93EiEKBmlucHV0cxgBIAMoCzIRLnN5c21sLkNhbGNPdXRwdXQSIgoHb3V0cHV0cxgCIAMoCzIRLnN5c21sLkNhbGNPdXRwdXQSIAoIdmVyZGljdHMYAyADKAsyDi5zeXNtbC5WZXJkaWN0EhYKDmVsYXBzZWRfbWljcm9zGAQgASgDEg0KBWVycm9yGAUgASgJEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbiLtAQoQUnVuU3dlZXBSZXNwb25zZRIdCgRyb3dzGAEgAygLMg8uc3lzbWwuU3dlZXBSb3cSEgoKcGFyYW1ldGVycxgCIAMoCRIPCgdzYW1wbGVkGAMgASgIEgwKBHNlZWQYBCABKAQSDQoFZXJyb3IYBSABKAkSJgoLZGlhZ25vc3RpY3MYBiADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAcgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhIiCglpbnN0YW5jZXMYCCADKAsyDy5zeXNtbC5JbnN0YW5jZSJuChdSdW5Eb2N1bWVudFF1ZXJ5UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhAKCHF1ZXJ5X2lkGAIgASgJEi0KCGJpbmRpbmdzGAMgAygLMhsuc3lzbWwuRG9jdW1lbnRRdWVyeUJpbmRpbmciTwoURG9jdW1lbnRRdWVyeUJpbmRpbmcSEQoJcGFyYW1ldGVyGAEgASgJEiQKBnZhbHVlcxgCIAMoCzIULnN5c21sLkRvY3VtZW50VmFsdWUi1QEKDURvY3VtZW50VmFsdWUSFAoKZWxlbWVudF9pZBgBIAEoCUgAEhYKDHN0cmluZ192YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoA0gAEhQKCnJlYWxfdmFsdWUYBCABKAFIABIUCgpib29sX3ZhbHVlGAUgASgISAASEgoIaW5maW5pdHkYBiABKAhIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASFAoMZWxlbWVudF90eXBlGAcgASgJQgYKBGtpbmQiIwoTRG9jdW1lbnRRdWVyeUNvbHVtbhIMCgRuYW1lGAEgASgJIjkKEURvY3VtZW50UXVlcnlDZWxsEiQKBnZhbHVlcxgBIAMoCzIULnN5c21sLkRvY3VtZW50VmFsdWUiYgoQRG9jdW1lbnRRdWVyeVJvdxIlCgdlbGVtZW50GAEgASgLMhQuc3lzbWwuRG9jdW1lbnRWYWx1ZRInCgVjZWxscxgCIAMoCzIYLnN5c21sLkRvY3VtZW50UXVlcnlDZWxsIm4KGFJ1bkRvY3VtZW50UXVlcnlSZXNwb25zZRIrCgdjb2x1bW5zGAEgAygLMhouc3lzbWwuRG9jdW1lbnRRdWVyeUNvbHVtbhIlCgRyb3dzGAIgAygLMhcuc3lzbWwuRG9jdW1lbnRRdWVyeVJvdyJAChVSZW5kZXJEb2N1bWVudFJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRITCgtkb2N1bWVudF9pZBgCIAEoCSIqChZSZW5kZXJEb2N1bWVudFJlc3BvbnNlEhAKCG1hcmtkb3duGAEgASgJKpMBCg1GYWlsdXJlUmVhc29uEh4KGkZBSUxVUkVfUkVBU09OX1VOU1BFQ0lGSUVEEAASHQoZRkFJTFVSRV9SRUFTT05fRVZBTFVBVElPThABEh0KGUZBSUxVUkVfUkVBU09OX1dST05HX0tJTkQQAhIkCiBGQUlMVVJFX1JFQVNPTl9BTUJJR1VPVVNfU1VCSkVDVBADKp0ECgtFZGl0RmFpbHVyZRIcChhFRElUX0ZBSUxVUkVfVU5TUEVDSUZJRUQQABIeChpFRElUX0ZBSUxVUkVfTk9fT1BFUkFUSU9OUxABEh8KG0VESVRfRkFJTFVSRV9VTktOT1dOX1RBUkdFVBACEiEKHUVESVRfRkFJTFVSRV9BTUJJR1VPVVNfVEFSR0VUEAMSGwoXRURJVF9GQUlMVVJFX05PVF9WQUxVRUQQBBIeChpFRElUX0ZBSUxVUkVfSU5WQUxJRF9WQUxVRRAFEh0KGUVESVRfRkFJTFVSRV9JTlZBTElEX05BTUUQBhIaChZFRElUX0ZBSUxVUkVfTk9UX05BTUVEEAcSIgoeRURJVF9GQUlMVVJFX1JFTkFNRV9SRUZFUkVOQ0VEEAgSIgoeRURJVF9GQUlMVVJFX09WRVJMQVBQSU5HX0VESVRTEAkSHwobRURJVF9GQUlMVVJFX1JFU1VMVF9JTlZBTElEEAoSHgoaRURJVF9GQUlMVVJFX09XTkVSX1VOS05PV04QCxIkCiBFRElUX0ZBSUxVUkVfT1dORVJfTk9UX05BTUVTUEFDRRAMEh0KGUVESVRfRkFJTFVSRV9JTExFR0FMX0tJTkQQDRIiCh5FRElUX0ZBSUxVUkVfTUVNQkVSX05BTUVfVEFLRU4QDhIiCh5FRElUX0ZBSUxVUkVfREVMRVRFX1JFRkVSRU5DRUQQDyqSAQoRUHJpbWl0aXZlT3BlcmF0b3ISIgoeUFJJTUlUSVZFX09QRVJBVE9SX1VOU1BFQ0lGSUVEEAASHAoYUFJJTUlUSVZFX09QRVJBVE9SX0VRVUFMEAESHgoaUFJJTUlUSVZFX09QRVJBVE9SX0dSRUFURVIQAhIbChdQUklNSVRJVkVfT1BFUkFUT1JfTEVTUxADKm4KEUNvbXBvc2l0ZU9wZXJhdG9yEiIKHkNPTVBPU0lURV9PUEVSQVRPUl9VTlNQRUNJRklFRBAAEhoKFkNPTVBPU0lURV9PUEVSQVRPUl9BTkQQARIZChVDT01QT1NJVEVfT1BFUkFUT1JfT1IQAjKkCwoMU3lzTUxTZXJ2aWNlEkQKDUdldFNlcnZlckluZm8SGC5zeXNtbC5TZXJ2ZXJJbmZvUmVxdWVzdBoZLnN5c21sLlNlcnZlckluZm9SZXNwb25zZRI+CglQYXJzZUZpbGUSFy5zeXNtbC5QYXJzZUZpbGVSZXF1ZXN0Ghguc3lzbWwuUGFyc2VGaWxlUmVzcG9uc2USRwoMUGFyc2VTb3VyY2VzEhouc3lzbWwuUGFyc2VTb3VyY2VzUmVxdWVzdBobLnN5c21sLlBhcnNlU291cmNlc1Jlc3BvbnNlEjsKCUdldFN5bWJvbBIXLnN5c21sLkdldFN5bWJvbFJlcXVlc3QaFS5zeXNtbC5TeW1ib2xSZXNwb25zZRJHCg5HZXREaWFnbm9zdGljcxIZLnN5c21sLkRpYWdub3N0aWNzUmVxdWVzdBoaLnN5c21sLkRpYWdub3N0aWNzUmVzcG9uc2USOwoIRXZhbHVhdGUSFi5zeXNtbC5FdmFsdWF0ZVJlcXVlc3QaFy5zeXNtbC5FdmFsdWF0ZVJlc3BvbnNlEkQKC0luc3RhbnRpYXRlEhkuc3lzbWwuSW5zdGFudGlhdGVSZXF1ZXN0Ghouc3lzbWwuSW5zdGFudGlhdGVSZXNwb25zZRJKCg1FeGVjdXRlQWN0aW9uEhsuc3lzbWwuRXhlY3V0ZUFjdGlvblJlcXVlc3QaHC5zeXNtbC5FeGVjdXRlQWN0aW9uUmVzcG9uc2USRwoMRXhlY3V0ZVN0YXRlEhouc3lzbWwuRXhlY3V0ZVN0YXRlUmVxdWVzdBobLnN5c21sLkV4ZWN1dGVTdGF0ZVJlc3BvbnNlEjgKB0NvbnZlcnQSFS5zeXNtbC5Db252ZXJ0UmVxdWVzdBoWLnN5c21sLkNvbnZlcnRSZXNwb25zZRJBCgpBcHBseUVkaXRzEhguc3lzbWwuQXBwbHlFZGl0c1JlcXVlc3QaGS5zeXNtbC5BcHBseUVkaXRzUmVzcG9uc2USUwoQVmVyaWZ5Q29uc3RyYWludBIeLnN5c21sLlZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0Gh8uc3lzbWwuVmVyaWZ5Q29uc3RyYWludFJlc3BvbnNlElYKEVZlcmlmeVJlcXVpcmVtZW50Eh8uc3lzbWwuVmVyaWZ5UmVxdWlyZW1lbnRSZXF1ZXN0GiAuc3lzbWwuVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRJZChJWZXJpZnlTYXRpc2ZhY3Rpb24SIC5zeXNtbC5WZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0GiEuc3lzbWwuVmVyaWZ5U2F0aXNmYWN0aW9uUmVzcG9uc2USRwoMRXZhbHVhdGVDYWxjEhouc3lzbWwuRXZhbHVhdGVDYWxjUmVxdWVzdBobLnN5c21sLkV2YWx1YXRlQ2FsY1Jlc3BvbnNlEkQKC1J1bkFuYWx5c2lzEhkuc3lzbWwuUnVuQW5hbHlzaXNSZXF1ZXN0Ghouc3lzbWwuUnVuQW5hbHlzaXNSZXNwb25zZRI7CghSdW5Td2VlcBIWLnN5c21sLlJ1blN3ZWVwUmVxdWVzdBoXLnN5c21sLlJ1blN3ZWVwUmVzcG9uc2USMgoFUXVlcnkSEy5zeXNtbC5RdWVyeVJlcXVlc3QaFC5zeXNtbC5RdWVyeVJlc3BvbnNlElMKEFJ1bkRvY3VtZW50UXVlcnkSHi5zeXNtbC5SdW5Eb2N1bWVudFF1ZXJ5UmVxdWVzdBofLnN5c21sLlJ1bkRvY3VtZW50UXVlcnlSZXNwb25zZRJNCg5SZW5kZXJEb2N1bWVudBIcLnN5c21sLlJlbmRlckRvY3VtZW50UmVxdWVzdBodLnN5c21sLlJlbmRlckRvY3VtZW50UmVzcG9uc2VCKlooZ2l0aHViLmNvbS9PcGVuLU1CRUUvT3BlblN5c01ML2FwaS9wcm90b2IGcHJvdG8z"); + fileDesc("CgtzeXNtbC5wcm90bxIFc3lzbWwi4gEKB1ZlcmRpY3QSDAoEa2luZBgBIAEoCRISCgplbGVtZW50X2lkGAIgASgJEg8KB2VsZW1lbnQYAyABKAkSDQoFaG9sZHMYBCABKAgSEQoJY29uZGl0aW9uGAUgASgJEhMKC2luc3RhbmNlX2lkGAYgASgDEhgKEGluc3RhbmNlX3R5cGVfaWQYByABKAkSDQoFZXJyb3IYCCABKAkSLAoOZmFpbHVyZV9yZWFzb24YCSABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uEhYKDnJlcXVpcmVtZW50X2lkGAogASgJIlsKF1ZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJEhkKEXN1YmplY3Rfc3ltYm9sX2lkGAMgASgJIpYBChhWZXJpZnlDb25zdHJhaW50UmVzcG9uc2USHwoHdmVyZGljdBgBIAEoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljIlwKGFZlcmlmeVJlcXVpcmVtZW50UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCSJtChNWZXJpZmljYXRpb25WZXJkaWN0Eg8KB2Nhc2VfaWQYASABKAkSDAoEa2luZBgCIAEoCRIOCgZkZXRhaWwYAyABKAkSDwoHc3ViY2FzZRgEIAEoCBIWCg5yZXF1aXJlbWVudF9pZBgFIAEoCSLSAQoZVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRIfCgd2ZXJkaWN0GAEgASgLMg4uc3lzbWwuVmVyZGljdBIiCglpbnN0YW5jZXMYAiADKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgDIAEoCRImCgtkaWFnbm9zdGljcxgEIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSOQoVdmVyaWZpY2F0aW9uX3ZlcmRpY3RzGAUgAygLMhouc3lzbWwuVmVyaWZpY2F0aW9uVmVyZGljdCJCChlWZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJIoICChpWZXJpZnlTYXRpc2ZhY3Rpb25SZXNwb25zZRIgCgh2ZXJkaWN0cxgBIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAUgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYBiADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0Il0KE0V2YWx1YXRlQ2FsY1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSHwoJYXJndW1lbnRzGAMgAygLMgwuc3lzbWwuVmFsdWUivQEKFEV2YWx1YXRlQ2FsY1Jlc3BvbnNlEhwKBnJlc3VsdBgBIAEoCzIMLnN5c21sLlZhbHVlEiIKB291dHB1dHMYAiADKAsyES5zeXNtbC5DYWxjT3V0cHV0Eg0KBWVycm9yGAMgASgJEiYKC2RpYWdub3N0aWNzGAQgAygLMhEuc3lzbWwuRGlhZ25vc3RpYxIsCg5mYWlsdXJlX3JlYXNvbhgFIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24iNwoKQ2FsY091dHB1dBIMCgRuYW1lGAEgASgJEhsKBXZhbHVlGAIgASgLMgwuc3lzbWwuVmFsdWUihAIKElJ1bkFuYWx5c2lzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCRIfCglhcmd1bWVudHMYBCADKAsyDC5zeXNtbC5WYWx1ZRJGCg9uYW1lZF9hcmd1bWVudHMYBSADKAsyLS5zeXNtbC5SdW5BbmFseXNpc1JlcXVlc3QuTmFtZWRBcmd1bWVudHNFbnRyeRpDChNOYW1lZEFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKfAgoTUnVuQW5hbHlzaXNSZXNwb25zZRIiCgdvdXRwdXRzGAEgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIgCgh2ZXJkaWN0cxgCIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAMgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYBCABKAkSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYByADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0IowBChBQYXJzZUZpbGVSZXF1ZXN0EhMKCWZpbGVfcGF0aBgBIAEoCUgAEhEKB2NvbnRlbnQYAiABKAlIABIYCgxjb250ZW50X2hhc2gYAyABKAlCAhgBEhAKCGxhbmd1YWdlGAQgASgJEhoKEnN0cmljdF9jb25mb3JtYW5jZRgFIAEoCEIICgZzb3VyY2UiYgoOU291cmNlRG9jdW1lbnQSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhAKCGxhbmd1YWdlGAMgASgJEgwKBG5hbWUYBCABKAlCCAoGc291cmNlIlsKE1BhcnNlU291cmNlc1JlcXVlc3QSKAoJZG9jdW1lbnRzGAEgAygLMhUuc3lzbWwuU291cmNlRG9jdW1lbnQSGgoSc3RyaWN0X2NvbmZvcm1hbmNlGAIgASgIIoMBChRQYXJzZVNvdXJjZXNSZXNwb25zZRISCgptb2RlbF9oYXNoGAEgASgJEiAKBXJvb3RzGAIgAygLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkifwoRUGFyc2VGaWxlUmVzcG9uc2USEgoKbW9kZWxfaGFzaBgBIAEoCRIfCgRyb290GAIgASgLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkiOQoQR2V0U3ltYm9sUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCSJCCg5TeW1ib2xSZXNwb25zZRIhCgZzeW1ib2wYASABKAsyES5zeXNtbC5TeW1ib2xJbmZvEg0KBWVycm9yGAIgASgJIigKEkRpYWdub3N0aWNzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJIkwKE0RpYWdub3N0aWNzUmVzcG9uc2USJgoLZGlhZ25vc3RpY3MYASADKAsyES5zeXNtbC5EaWFnbm9zdGljEg0KBWVycm9yGAIgASgJIm8KD0V2YWx1YXRlUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhIKCmV4cHJlc3Npb24YAiABKAkSGQoRY29udGV4dF9zeW1ib2xfaWQYAyABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYBCABKAkiZwoQRXZhbHVhdGVSZXNwb25zZRIcCgZyZXN1bHQYASABKAsyDC5zeXNtbC5WYWx1ZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMiwgEKCEluc3RhbmNlEgoKAmlkGAEgASgDEhYKDnR5cGVfc3ltYm9sX2lkGAIgASgJEjoKDmZlYXR1cmVfdmFsdWVzGAQgAygLMiIuc3lzbWwuSW5zdGFuY2UuRmVhdHVyZVZhbHVlc0VudHJ5GkkKEkZlYXR1cmVWYWx1ZXNFbnRyeRILCgNrZXkYASABKAkSIgoFdmFsdWUYAiABKAsyEy5zeXNtbC5GZWF0dXJlVmFsdWU6AjgBSgQIAxAEUgVzbG90cyKEAQoMRmVhdHVyZVZhbHVlEhQKDGZlYXR1cmVfbmFtZRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlEhwKBnZhbHVlcxgDIAMoCzIMLnN5c21sLlZhbHVlEhQKDG1hdGVyaWFsaXplZBgEIAEoCBINCgVlcnJvchgFIAEoCSI7ChJJbnN0YW50aWF0ZVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkikwEKE0luc3RhbnRpYXRlUmVzcG9uc2USIQoIaW5zdGFuY2UYASABKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSIgoJaW5zdGFuY2VzGAQgAygLMg8uc3lzbWwuSW5zdGFuY2UiugEKFEV4ZWN1dGVBY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGAoQYWN0aW9uX3N5bWJvbF9pZBgCIAEoCRI3CgZpbnB1dHMYAyADKAsyJy5zeXNtbC5FeGVjdXRlQWN0aW9uUmVxdWVzdC5JbnB1dHNFbnRyeRo7CgtJbnB1dHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKFUV4ZWN1dGVBY3Rpb25SZXNwb25zZRI6CgdvdXRwdXRzGAEgAygLMikuc3lzbWwuRXhlY3V0ZUFjdGlvblJlc3BvbnNlLk91dHB1dHNFbnRyeRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMaPAoMT3V0cHV0c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASJaChNFeGVjdXRlU3RhdGVSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSHwoXc3RhdGVfbWFjaGluZV9zeW1ib2xfaWQYAiABKAkSDgoGZXZlbnRzGAMgAygJIu4BChRFeGVjdXRlU3RhdGVSZXNwb25zZRIWCg5zdGF0ZXNfdmlzaXRlZBgBIAMoCRJECg1maW5hbF9jb250ZXh0GAIgAygLMi0uc3lzbWwuRXhlY3V0ZVN0YXRlUmVzcG9uc2UuRmluYWxDb250ZXh0RW50cnkSDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljGkEKEUZpbmFsQ29udGV4dEVudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKgAQoOQ29udmVydFJlcXVlc3QSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhQKCm1vZGVsX2hhc2gYBiABKAlIABITCgtmcm9tX2Zvcm1hdBgDIAEoCRIRCgl0b19mb3JtYXQYBCABKAkSHgoWdG9sZXJhdGVfc3ludGF4X2Vycm9ycxgFIAEoCEIICgZzb3VyY2UitAEKD0NvbnZlcnRSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEhMKC2Zyb21fZm9ybWF0GAIgASgJEhEKCXRvX2Zvcm1hdBgDIAEoCRINCgVlcnJvchgEIAEoCRImCgtkaWFnbm9zdGljcxgFIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSFAoMZXhwZXJpbWVudGFsGAYgASgIEhsKE2V4cGVyaW1lbnRhbF9ub3RpY2UYByABKAkiUQoRQXBwbHlFZGl0c1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIoCgpvcGVyYXRpb25zGAIgAygLMhQuc3lzbWwuRWRpdE9wZXJhdGlvbiK8AQoNRWRpdE9wZXJhdGlvbhIoCglzZXRfdmFsdWUYASABKAsyEy5zeXNtbC5TZXRWYWx1ZUVkaXRIABIjCgZyZW5hbWUYAiABKAsyES5zeXNtbC5SZW5hbWVFZGl0SAASKgoKYWRkX21lbWJlchgDIAEoCzIULnN5c21sLkFkZE1lbWJlckVkaXRIABIjCgZkZWxldGUYBCABKAsyES5zeXNtbC5EZWxldGVFZGl0SABCCwoJb3BlcmF0aW9uIoIBCg1BZGRNZW1iZXJFZGl0Eg0KBW93bmVyGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEbmFtZRgDIAEoCRIMCgR0eXBlGAQgASgJEhQKDG11bHRpcGxpY2l0eRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtzcGVjaWFsaXplcxgHIAMoCSItCgpEZWxldGVFZGl0Eg4KBnRhcmdldBgBIAEoCRIPCgdjYXNjYWRlGAIgASgIIi0KDFNldFZhbHVlRWRpdBIOCgZ0YXJnZXQYASABKAkSDQoFdmFsdWUYAiABKAkiLgoKUmVuYW1lRWRpdBIOCgZ0YXJnZXQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiwgEKEkFwcGx5RWRpdHNSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEiMKB2FwcGxpZWQYAiADKAsyEi5zeXNtbC5BcHBsaWVkRWRpdBINCgVlcnJvchgDIAEoCRIjCgdmYWlsdXJlGAQgASgOMhIuc3lzbWwuRWRpdEZhaWx1cmUSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEhoKEnJlZmVycmluZ19lbGVtZW50cxgGIAMoCSJ6CgtBcHBsaWVkRWRpdBIXCg9vcGVyYXRpb25faW5kZXgYASABKAUSDgoGdGFyZ2V0GAIgASgJEg4KBm9mZnNldBgDIAEoBRIOCgZsZW5ndGgYBCABKAUSEAoIb2xkX3RleHQYBSABKAkSEAoIbmV3X3RleHQYBiABKAki/QIKClN5bWJvbEluZm8SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRraW5kGAMgASgJEjEKCG1ldGFkYXRhGAQgAygLMh8uc3lzbWwuU3ltYm9sSW5mby5NZXRhZGF0YUVudHJ5EhEKCWNoaWxkX2lkcxgFIAMoCRIoCgphdHRyaWJ1dGVzGAYgAygLMhQuc3lzbWwuQXR0cmlidXRlSW5mbxIiCgl0eXBlX2luZm8YByABKAsyDy5zeXNtbC5UeXBlSW5mbxItCgxtdWx0aXBsaWNpdHkYCCABKAsyFy5zeXNtbC5NdWx0aXBsaWNpdHlJbmZvEi4KD3NwZWNpYWxpemF0aW9ucxgJIAMoCzIVLnN5c21sLlNwZWNpYWxpemF0aW9uEiMKG3dpdGhoZWxkX2xpYnJhcnlfYXR0cmlidXRlcxgKIAEoBRovCg1NZXRhZGF0YUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiWAoOU3BlY2lhbGl6YXRpb24SDAoEa2luZBgBIAEoCRIQCghkZWNsYXJlZBgCIAEoCRIRCgl0YXJnZXRfaWQYAyABKAkSEwoLdGFyZ2V0X2tpbmQYBCABKAkilQEKCFR5cGVJbmZvEhAKCGRlY2xhcmVkGAEgASgJEhMKC3Jlc29sdmVkX2lkGAIgASgJEhUKDXJlc29sdmVkX2tpbmQYAyABKAkSEQoJcHJpbWl0aXZlGAQgASgJEhgKEHByaW1pdGl2ZV9zb3VyY2UYBSABKAkSEAoIcXVhbnRpdHkYBiABKAgSDAoEdW5pdBgHIAEoCSIwChBNdWx0aXBsaWNpdHlJbmZvEg0KBWxvd2VyGAEgASgJEg0KBXVwcGVyGAIgASgJIlYKDUF0dHJpYnV0ZUluZm8SDAoEbmFtZRgBIAEoCRIMCgR0eXBlGAIgASgJEhsKBXZhbHVlGAMgASgLMgwuc3lzbWwuVmFsdWUSDAoEdW5pdBgEIAEoCSL2AwoFVmFsdWUSEwoJaW50X3ZhbHVlGAEgASgDSAASFAoKcmVhbF92YWx1ZRgCIAEoAUgAEhQKCmJvb2xfdmFsdWUYAyABKAhIABIWCgxzdHJpbmdfdmFsdWUYBCABKAlIABIVCgtpbnN0YW5jZV9pZBgFIAEoA0gAEigKCHNlcXVlbmNlGAYgASgLMhQuc3lzbWwuVmFsdWVTZXF1ZW5jZUgAEg4KBG51bGwYByABKAlIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASKgoMZW51bV9saXRlcmFsGAkgASgLMhIuc3lzbWwuRW51bUxpdGVyYWxIABIPCgV1bnNldBgKIAEoCEgAEiEKB2NvbXBsZXgYCyABKAsyDi5zeXNtbC5Db21wbGV4SAASHQoFYXJyYXkYDCABKAsyDC5zeXNtbC5BcnJheUgAEh8KBnZlY3RvchgNIAEoCzINLnN5c21sLlZlY3RvckgAEjAKD3ZlY3Rvcl9xdWFudGl0eRgOIAEoCzIVLnN5c21sLlZlY3RvclF1YW50aXR5SAASMAoPbWVhc3VyZW1lbnRfcmVmGA8gASgLMhUuc3lzbWwuTWVhc3VyZW1lbnRSZWZIABISCghpbmZpbml0eRgQIAEoCEgAQgYKBGtpbmQiOwoFQXJyYXkSEgoKZGltZW5zaW9ucxgBIAMoAxIeCghlbGVtZW50cxgCIAMoCzIMLnN5c21sLlZhbHVlIioKBlZlY3RvchIgCgpjb21wb25lbnRzGAEgAygLMgwuc3lzbWwuVmFsdWUiNQoOVmVjdG9yUXVhbnRpdHkSIwoKY29tcG9uZW50cxgBIAMoCzIPLnN5c21sLlF1YW50aXR5IioKB0NvbXBsZXgSDAoEcmVhbBgBIAEoARIRCglpbWFnaW5hcnkYAiABKAEiRwoLRW51bUxpdGVyYWwSEgoKbGl0ZXJhbF9pZBgBIAEoCRIWCg5lbnVtZXJhdGlvbl9pZBgCIAEoCRIMCgRuYW1lGAMgASgJIi8KDVZhbHVlU2VxdWVuY2USHgoIZWxlbWVudHMYASADKAsyDC5zeXNtbC5WYWx1ZSJ8CghRdWFudGl0eRIXCg1pbnRfbWFnbml0dWRlGAEgASgDSAASGAoOcmVhbF9tYWduaXR1ZGUYAiABKAFIABIMCgR1bml0GAMgASgJEiIKCXVuaXRfdGVybRgEIAEoCzIPLnN5c21sLlVuaXRUZXJtQgsKCW1hZ25pdHVkZSJTCg5NZWFzdXJlbWVudFJlZhIMCgR1bml0GAEgASgJEiIKCXVuaXRfdGVybRgCIAEoCzIPLnN5c21sLlVuaXRUZXJtEg8KB3VuaXRfaWQYAyABKAkiVAoIVW5pdFRlcm0SEQoJc2NhbGVfbnVtGAEgASgBEhEKCXNjYWxlX2RlbhgCIAEoARIiCgdmYWN0b3JzGAMgAygLMhEuc3lzbWwuVW5pdEZhY3RvciIvCgpVbml0RmFjdG9yEg8KB3VuaXRfaWQYASABKAkSEAoIZXhwb25lbnQYAiABKAEiSgoKRGlhZ25vc3RpYxIQCghzZXZlcml0eRgBIAEoCRIPCgdtZXNzYWdlGAIgASgJEhkKBHNwYW4YAyABKAsyCy5zeXNtbC5TcGFuIl4KBFNwYW4SDAoEZmlsZRgBIAEoCRISCgpzdGFydF9saW5lGAIgASgFEhEKCXN0YXJ0X2NvbBgDIAEoBRIQCghlbmRfbGluZRgEIAEoBRIPCgdlbmRfY29sGAUgASgFIhMKEVNlcnZlckluZm9SZXF1ZXN0IjsKElNlcnZlckluZm9SZXNwb25zZRIPCgd2ZXJzaW9uGAEgASgJEhQKDGNhcGFiaWxpdGllcxgCIAMoCSJTCgxRdWVyeVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIbCgVxdWVyeRgCIAEoCzIMLnN5c21sLlF1ZXJ5EhIKCm9zbGNfcXVlcnkYAyABKAkiPAoNUXVlcnlSZXNwb25zZRIrCghlbGVtZW50cxgBIAMoCzIZLnN5c21sLlF1ZXJ5UmVzdWx0RWxlbWVudCJICgVRdWVyeRINCgVzY29wZRgBIAMoCRIOCgZzZWxlY3QYAiADKAkSIAoFd2hlcmUYAyABKAsyES5zeXNtbC5Db25zdHJhaW50InwKCkNvbnN0cmFpbnQSLwoJcHJpbWl0aXZlGAEgASgLMhouc3lzbWwuUHJpbWl0aXZlQ29uc3RyYWludEgAEi8KCWNvbXBvc2l0ZRgCIAEoCzIaLnN5c21sLkNvbXBvc2l0ZUNvbnN0cmFpbnRIAEIMCgpjb25zdHJhaW50InMKE1ByaW1pdGl2ZUNvbnN0cmFpbnQSDwoHaW52ZXJzZRgBIAEoCBIQCghwcm9wZXJ0eRgCIAEoCRIqCghvcGVyYXRvchgDIAEoDjIYLnN5c21sLlByaW1pdGl2ZU9wZXJhdG9yEg0KBXZhbHVlGAQgAygJImgKE0NvbXBvc2l0ZUNvbnN0cmFpbnQSKgoIb3BlcmF0b3IYASABKA4yGC5zeXNtbC5Db21wb3NpdGVPcGVyYXRvchIlCgpjb25zdHJhaW50GAIgAygLMhEuc3lzbWwuQ29uc3RyYWludCKgAQoSUXVlcnlSZXN1bHRFbGVtZW50EgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSPQoKcHJvcGVydGllcxgDIAMoCzIpLnN5c21sLlF1ZXJ5UmVzdWx0RWxlbWVudC5Qcm9wZXJ0aWVzRW50cnkaMQoPUHJvcGVydGllc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEicwoKU3dlZXBSYW5nZRIRCglwYXJhbWV0ZXIYASABKAkSGwoFc3RhcnQYAiABKAsyDC5zeXNtbC5WYWx1ZRIZCgNlbmQYAyABKAsyDC5zeXNtbC5WYWx1ZRIaCgRzdGVwGAQgASgLMgwuc3lzbWwuVmFsdWUiwAIKD1J1blN3ZWVwUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCRIfCglhcmd1bWVudHMYBCADKAsyDC5zeXNtbC5WYWx1ZRJDCg9uYW1lZF9hcmd1bWVudHMYBSADKAsyKi5zeXNtbC5SdW5Td2VlcFJlcXVlc3QuTmFtZWRBcmd1bWVudHNFbnRyeRIhCgZyYW5nZXMYBiADKAsyES5zeXNtbC5Td2VlcFJhbmdlEg8KB3NhbXBsZXMYByABKAMSDAoEc2VlZBgIIAEoBBpDChNOYW1lZEFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASLIAQoIU3dlZXBSb3cSIQoGaW5wdXRzGAEgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIiCgdvdXRwdXRzGAIgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIgCgh2ZXJkaWN0cxgDIAMoCzIOLnN5c21sLlZlcmRpY3QSFgoOZWxhcHNlZF9taWNyb3MYBCABKAMSDQoFZXJyb3IYBSABKAkSLAoOZmFpbHVyZV9yZWFzb24YBiABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uIu0BChBSdW5Td2VlcFJlc3BvbnNlEh0KBHJvd3MYASADKAsyDy5zeXNtbC5Td2VlcFJvdxISCgpwYXJhbWV0ZXJzGAIgAygJEg8KB3NhbXBsZWQYAyABKAgSDAoEc2VlZBgEIAEoBBINCgVlcnJvchgFIAEoCRImCgtkaWFnbm9zdGljcxgGIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSLAoOZmFpbHVyZV9yZWFzb24YByABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uEiIKCWluc3RhbmNlcxgIIAMoCzIPLnN5c21sLkluc3RhbmNlIm4KF1J1bkRvY3VtZW50UXVlcnlSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEAoIcXVlcnlfaWQYAiABKAkSLQoIYmluZGluZ3MYAyADKAsyGy5zeXNtbC5Eb2N1bWVudFF1ZXJ5QmluZGluZyJPChREb2N1bWVudFF1ZXJ5QmluZGluZxIRCglwYXJhbWV0ZXIYASABKAkSJAoGdmFsdWVzGAIgAygLMhQuc3lzbWwuRG9jdW1lbnRWYWx1ZSLVAQoNRG9jdW1lbnRWYWx1ZRIUCgplbGVtZW50X2lkGAEgASgJSAASFgoMc3RyaW5nX3ZhbHVlGAIgASgJSAASEwoJaW50X3ZhbHVlGAMgASgDSAASFAoKcmVhbF92YWx1ZRgEIAEoAUgAEhQKCmJvb2xfdmFsdWUYBSABKAhIABISCghpbmZpbml0eRgGIAEoCEgAEiMKCHF1YW50aXR5GAggASgLMg8uc3lzbWwuUXVhbnRpdHlIABIUCgxlbGVtZW50X3R5cGUYByABKAlCBgoEa2luZCIjChNEb2N1bWVudFF1ZXJ5Q29sdW1uEgwKBG5hbWUYASABKAkiOQoRRG9jdW1lbnRRdWVyeUNlbGwSJAoGdmFsdWVzGAEgAygLMhQuc3lzbWwuRG9jdW1lbnRWYWx1ZSJiChBEb2N1bWVudFF1ZXJ5Um93EiUKB2VsZW1lbnQYASABKAsyFC5zeXNtbC5Eb2N1bWVudFZhbHVlEicKBWNlbGxzGAIgAygLMhguc3lzbWwuRG9jdW1lbnRRdWVyeUNlbGwibgoYUnVuRG9jdW1lbnRRdWVyeVJlc3BvbnNlEisKB2NvbHVtbnMYASADKAsyGi5zeXNtbC5Eb2N1bWVudFF1ZXJ5Q29sdW1uEiUKBHJvd3MYAiADKAsyFy5zeXNtbC5Eb2N1bWVudFF1ZXJ5Um93IkAKFVJlbmRlckRvY3VtZW50UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhMKC2RvY3VtZW50X2lkGAIgASgJIioKFlJlbmRlckRvY3VtZW50UmVzcG9uc2USEAoIbWFya2Rvd24YASABKAkqkwEKDUZhaWx1cmVSZWFzb24SHgoaRkFJTFVSRV9SRUFTT05fVU5TUEVDSUZJRUQQABIdChlGQUlMVVJFX1JFQVNPTl9FVkFMVUFUSU9OEAESHQoZRkFJTFVSRV9SRUFTT05fV1JPTkdfS0lORBACEiQKIEZBSUxVUkVfUkVBU09OX0FNQklHVU9VU19TVUJKRUNUEAMqnQQKC0VkaXRGYWlsdXJlEhwKGEVESVRfRkFJTFVSRV9VTlNQRUNJRklFRBAAEh4KGkVESVRfRkFJTFVSRV9OT19PUEVSQVRJT05TEAESHwobRURJVF9GQUlMVVJFX1VOS05PV05fVEFSR0VUEAISIQodRURJVF9GQUlMVVJFX0FNQklHVU9VU19UQVJHRVQQAxIbChdFRElUX0ZBSUxVUkVfTk9UX1ZBTFVFRBAEEh4KGkVESVRfRkFJTFVSRV9JTlZBTElEX1ZBTFVFEAUSHQoZRURJVF9GQUlMVVJFX0lOVkFMSURfTkFNRRAGEhoKFkVESVRfRkFJTFVSRV9OT1RfTkFNRUQQBxIiCh5FRElUX0ZBSUxVUkVfUkVOQU1FX1JFRkVSRU5DRUQQCBIiCh5FRElUX0ZBSUxVUkVfT1ZFUkxBUFBJTkdfRURJVFMQCRIfChtFRElUX0ZBSUxVUkVfUkVTVUxUX0lOVkFMSUQQChIeChpFRElUX0ZBSUxVUkVfT1dORVJfVU5LTk9XThALEiQKIEVESVRfRkFJTFVSRV9PV05FUl9OT1RfTkFNRVNQQUNFEAwSHQoZRURJVF9GQUlMVVJFX0lMTEVHQUxfS0lORBANEiIKHkVESVRfRkFJTFVSRV9NRU1CRVJfTkFNRV9UQUtFThAOEiIKHkVESVRfRkFJTFVSRV9ERUxFVEVfUkVGRVJFTkNFRBAPKpIBChFQcmltaXRpdmVPcGVyYXRvchIiCh5QUklNSVRJVkVfT1BFUkFUT1JfVU5TUEVDSUZJRUQQABIcChhQUklNSVRJVkVfT1BFUkFUT1JfRVFVQUwQARIeChpQUklNSVRJVkVfT1BFUkFUT1JfR1JFQVRFUhACEhsKF1BSSU1JVElWRV9PUEVSQVRPUl9MRVNTEAMqbgoRQ29tcG9zaXRlT3BlcmF0b3ISIgoeQ09NUE9TSVRFX09QRVJBVE9SX1VOU1BFQ0lGSUVEEAASGgoWQ09NUE9TSVRFX09QRVJBVE9SX0FORBABEhkKFUNPTVBPU0lURV9PUEVSQVRPUl9PUhACMqQLCgxTeXNNTFNlcnZpY2USRAoNR2V0U2VydmVySW5mbxIYLnN5c21sLlNlcnZlckluZm9SZXF1ZXN0Ghkuc3lzbWwuU2VydmVySW5mb1Jlc3BvbnNlEj4KCVBhcnNlRmlsZRIXLnN5c21sLlBhcnNlRmlsZVJlcXVlc3QaGC5zeXNtbC5QYXJzZUZpbGVSZXNwb25zZRJHCgxQYXJzZVNvdXJjZXMSGi5zeXNtbC5QYXJzZVNvdXJjZXNSZXF1ZXN0Ghsuc3lzbWwuUGFyc2VTb3VyY2VzUmVzcG9uc2USOwoJR2V0U3ltYm9sEhcuc3lzbWwuR2V0U3ltYm9sUmVxdWVzdBoVLnN5c21sLlN5bWJvbFJlc3BvbnNlEkcKDkdldERpYWdub3N0aWNzEhkuc3lzbWwuRGlhZ25vc3RpY3NSZXF1ZXN0Ghouc3lzbWwuRGlhZ25vc3RpY3NSZXNwb25zZRI7CghFdmFsdWF0ZRIWLnN5c21sLkV2YWx1YXRlUmVxdWVzdBoXLnN5c21sLkV2YWx1YXRlUmVzcG9uc2USRAoLSW5zdGFudGlhdGUSGS5zeXNtbC5JbnN0YW50aWF0ZVJlcXVlc3QaGi5zeXNtbC5JbnN0YW50aWF0ZVJlc3BvbnNlEkoKDUV4ZWN1dGVBY3Rpb24SGy5zeXNtbC5FeGVjdXRlQWN0aW9uUmVxdWVzdBocLnN5c21sLkV4ZWN1dGVBY3Rpb25SZXNwb25zZRJHCgxFeGVjdXRlU3RhdGUSGi5zeXNtbC5FeGVjdXRlU3RhdGVSZXF1ZXN0Ghsuc3lzbWwuRXhlY3V0ZVN0YXRlUmVzcG9uc2USOAoHQ29udmVydBIVLnN5c21sLkNvbnZlcnRSZXF1ZXN0GhYuc3lzbWwuQ29udmVydFJlc3BvbnNlEkEKCkFwcGx5RWRpdHMSGC5zeXNtbC5BcHBseUVkaXRzUmVxdWVzdBoZLnN5c21sLkFwcGx5RWRpdHNSZXNwb25zZRJTChBWZXJpZnlDb25zdHJhaW50Eh4uc3lzbWwuVmVyaWZ5Q29uc3RyYWludFJlcXVlc3QaHy5zeXNtbC5WZXJpZnlDb25zdHJhaW50UmVzcG9uc2USVgoRVmVyaWZ5UmVxdWlyZW1lbnQSHy5zeXNtbC5WZXJpZnlSZXF1aXJlbWVudFJlcXVlc3QaIC5zeXNtbC5WZXJpZnlSZXF1aXJlbWVudFJlc3BvbnNlElkKElZlcmlmeVNhdGlzZmFjdGlvbhIgLnN5c21sLlZlcmlmeVNhdGlzZmFjdGlvblJlcXVlc3QaIS5zeXNtbC5WZXJpZnlTYXRpc2ZhY3Rpb25SZXNwb25zZRJHCgxFdmFsdWF0ZUNhbGMSGi5zeXNtbC5FdmFsdWF0ZUNhbGNSZXF1ZXN0Ghsuc3lzbWwuRXZhbHVhdGVDYWxjUmVzcG9uc2USRAoLUnVuQW5hbHlzaXMSGS5zeXNtbC5SdW5BbmFseXNpc1JlcXVlc3QaGi5zeXNtbC5SdW5BbmFseXNpc1Jlc3BvbnNlEjsKCFJ1blN3ZWVwEhYuc3lzbWwuUnVuU3dlZXBSZXF1ZXN0Ghcuc3lzbWwuUnVuU3dlZXBSZXNwb25zZRIyCgVRdWVyeRITLnN5c21sLlF1ZXJ5UmVxdWVzdBoULnN5c21sLlF1ZXJ5UmVzcG9uc2USUwoQUnVuRG9jdW1lbnRRdWVyeRIeLnN5c21sLlJ1bkRvY3VtZW50UXVlcnlSZXF1ZXN0Gh8uc3lzbWwuUnVuRG9jdW1lbnRRdWVyeVJlc3BvbnNlEk0KDlJlbmRlckRvY3VtZW50Ehwuc3lzbWwuUmVuZGVyRG9jdW1lbnRSZXF1ZXN0Gh0uc3lzbWwuUmVuZGVyRG9jdW1lbnRSZXNwb25zZUIqWihnaXRodWIuY29tL09wZW4tTUJFRS9PcGVuU3lzTUwvYXBpL3Byb3RvYgZwcm90bzM"); /** * Verdict is one verification's answer: whether the condition held, and, when @@ -2119,6 +2119,16 @@ export type Value = Message<"sysml.Value"> & { */ value: MeasurementRef; case: "measurementRef"; + } | { + /** + * The unbounded value `*`, which is no number and no string: ordered above + * every finite magnitude and refused by arithmetic. Always true when set, + * as DocumentValue.infinity is. + * + * @generated from field: bool infinity = 16; + */ + value: boolean; + case: "infinity"; } | { case: undefined; value?: undefined }; }; diff --git a/clients/node/test/values.test.ts b/clients/node/test/values.test.ts index 0d01ace11..730177aa7 100644 --- a/clients/node/test/values.test.ts +++ b/clients/node/test/values.test.ts @@ -460,3 +460,17 @@ test("every failure reason has a name", () => { assert.equal(failureCause(FailureReason.WRONG_KIND), "wrong_kind"); assert.equal(failureCause(FailureReason.AMBIGUOUS_SUBJECT), "ambiguous_subject"); }); + +test("only an asserted infinity arm is the unbounded value", () => { + const asserted = create(ValueSchema, { kind: { case: "infinity", value: true } }); + assert.deepEqual(decodeValue(asserted), { kind: "infinity" }); + const denied = create(ValueSchema, { kind: { case: "infinity", value: false } }); + assert.throws(() => decodeValue(denied), MalformedValueError); + const nested = create(ValueSchema, { + kind: { + case: "sequence", + value: create(ValueSequenceSchema, { elements: [denied] }), + }, + }); + assert.throws(() => decodeValue(nested), MalformedValueError); +}); diff --git a/clients/python/opensysml/capabilities.py b/clients/python/opensysml/capabilities.py index 07bfbaf21..abd9e0fd6 100644 --- a/clients/python/opensysml/capabilities.py +++ b/clients/python/opensysml/capabilities.py @@ -107,6 +107,12 @@ #: verification case. CAPABILITY_VERIFICATION_VERDICTS = "verification_verdicts" +#: The unbounded value ``*`` as ``Value.infinity``, read as +#: :data:`~opensysml.values.INFINITY`. Without it the service sends an +#: unsupported null naming it, which is an error, and refuses one sent to it +#: with ``UNIMPLEMENTED``. +CAPABILITY_INFINITY_VALUE = "infinity_value" + @dataclass(frozen=True) class ServerInfo: diff --git a/clients/python/opensysml/connection.py b/clients/python/opensysml/connection.py index a5fcbdb6c..225b08551 100644 --- a/clients/python/opensysml/connection.py +++ b/clients/python/opensysml/connection.py @@ -21,6 +21,7 @@ CAPABILITY_DOCUMENT_QUERY, CAPABILITY_EVALUATE_SUBJECT, CAPABILITY_FEATURE_VALUES, + CAPABILITY_INFINITY_VALUE, CAPABILITY_MEASUREMENT_REFS, CAPABILITY_QUERY, CAPABILITY_RENDER_DOCUMENT, @@ -62,6 +63,7 @@ Quantity, Vector, VectorQuantity, + _Infinity, value_to_python, ) from opensysml.verdict import ( @@ -1660,6 +1662,14 @@ def _require_measurement_refs(self): upgrade_remedy(CAPABILITY_MEASUREMENT_REFS), ) + def _require_infinity_value(self): + """Refuse to send the unbounded value ``*`` a service without ``infinity_value`` would read as null.""" + require( + self.server_info(), + CAPABILITY_INFINITY_VALUE, + upgrade_remedy(CAPABILITY_INFINITY_VALUE), + ) + def _require_feature_values(self): """Refuse instances from a service that populates only the removed `slots` field.""" require( @@ -1704,6 +1714,9 @@ def _python_to_value(self, py_value): return sysml_pb2.Value(instance_id=py_value.id) elif isinstance(py_value, Quantity): return sysml_pb2.Value(quantity=py_value.to_pb()) + elif isinstance(py_value, _Infinity): + self._require_infinity_value() + return sysml_pb2.Value(infinity=True) elif isinstance(py_value, MeasurementRef): self._require_measurement_refs() return sysml_pb2.Value(measurement_ref=py_value.to_pb()) diff --git a/clients/python/opensysml/document.py b/clients/python/opensysml/document.py index 282adfa27..564c0ccb7 100644 --- a/clients/python/opensysml/document.py +++ b/clients/python/opensysml/document.py @@ -17,7 +17,7 @@ from opensysml.errors import OpenSysMLError, UnsupportedValueError from opensysml.proto import sysml_pb2 -from opensysml.values import Quantity +from opensysml.values import INFINITY, Quantity, _Infinity class DocumentQueryError(OpenSysMLError, ValueError): @@ -41,17 +41,6 @@ def __str__(self): return f"{self.id} ({self.type})" if self.type else self.id -class _Infinity: - """The unbounded multiplicity a query may answer with.""" - - def __repr__(self): - return "INFINITY" - - -#: An unbounded multiplicity in an answered cell. Only ever answered: binding -#: it is refused by the service. -INFINITY = _Infinity() - #: What a binding value or an answered cell value may be. DocumentValue = Union[ElementRef, str, int, float, bool, Quantity, _Infinity] diff --git a/clients/python/opensysml/proto/sysml_pb2.py b/clients/python/opensysml/proto/sysml_pb2.py index 1e1b1dfc4..391c35afc 100644 --- a/clients/python/opensysml/proto/sysml_pb2.py +++ b/clients/python/opensysml/proto/sysml_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bsysml.proto\x12\x05sysml\"\xe2\x01\n\x07Verdict\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x12\n\nelement_id\x18\x02 \x01(\t\x12\x0f\n\x07\x65lement\x18\x03 \x01(\t\x12\r\n\x05holds\x18\x04 \x01(\x08\x12\x11\n\tcondition\x18\x05 \x01(\t\x12\x13\n\x0binstance_id\x18\x06 \x01(\x03\x12\x18\n\x10instance_type_id\x18\x07 \x01(\t\x12\r\n\x05\x65rror\x18\x08 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\t \x01(\x0e\x32\x14.sysml.FailureReason\x12\x16\n\x0erequirement_id\x18\n \x01(\t\"[\n\x17VerifyConstraintRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"\x96\x01\n\x18VerifyConstraintResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\"\\\n\x18VerifyRequirementRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"m\n\x13VerificationVerdict\x12\x0f\n\x07\x63\x61se_id\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65tail\x18\x03 \x01(\t\x12\x0f\n\x07subcase\x18\x04 \x01(\x08\x12\x16\n\x0erequirement_id\x18\x05 \x01(\t\"\xd2\x01\n\x19VerifyRequirementResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x39\n\x15verification_verdicts\x18\x05 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"B\n\x19VerifySatisfactionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x82\x02\n\x1aVerifySatisfactionResponse\x12 \n\x08verdicts\x18\x01 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x06 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"]\n\x13\x45valuateCalcRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x1f\n\targuments\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\"\xbd\x01\n\x14\x45valuateCalcResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\"7\n\nCalcOutput\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\"\x84\x02\n\x12RunAnalysisRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x46\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32-.sysml.RunAnalysisRequest.NamedArgumentsEntry\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\x9f\x02\n\x13RunAnalysisResponse\x12\"\n\x07outputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x02 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x03 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x07 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"\x8c\x01\n\x10ParseFileRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x18\n\x0c\x63ontent_hash\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08language\x18\x04 \x01(\t\x12\x1a\n\x12strict_conformance\x18\x05 \x01(\x08\x42\x08\n\x06source\"b\n\x0eSourceDocument\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x10\n\x08language\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\tB\x08\n\x06source\"[\n\x13ParseSourcesRequest\x12(\n\tdocuments\x18\x01 \x03(\x0b\x32\x15.sysml.SourceDocument\x12\x1a\n\x12strict_conformance\x18\x02 \x01(\x08\"\x83\x01\n\x14ParseSourcesResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12 \n\x05roots\x18\x02 \x03(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\x7f\n\x11ParseFileResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x04root\x18\x02 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"9\n\x10GetSymbolRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"B\n\x0eSymbolResponse\x12!\n\x06symbol\x18\x01 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"(\n\x12\x44iagnosticsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\"L\n\x13\x44iagnosticsResponse\x12&\n\x0b\x64iagnostics\x18\x01 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"o\n\x0f\x45valuateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x12\n\nexpression\x18\x02 \x01(\t\x12\x19\n\x11\x63ontext_symbol_id\x18\x03 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x04 \x01(\t\"g\n\x10\x45valuateResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\"\xc2\x01\n\x08Instance\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x16\n\x0etype_symbol_id\x18\x02 \x01(\t\x12:\n\x0e\x66\x65\x61ture_values\x18\x04 \x03(\x0b\x32\".sysml.Instance.FeatureValuesEntry\x1aI\n\x12\x46\x65\x61tureValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.sysml.FeatureValue:\x02\x38\x01J\x04\x08\x03\x10\x04R\x05slots\"\x84\x01\n\x0c\x46\x65\x61tureValue\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\x12\x14\n\x0cmaterialized\x18\x04 \x01(\x08\x12\r\n\x05\x65rror\x18\x05 \x01(\t\";\n\x12InstantiateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x93\x01\n\x13InstantiateResponse\x12!\n\x08instance\x18\x01 \x01(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\"\n\tinstances\x18\x04 \x03(\x0b\x32\x0f.sysml.Instance\"\xba\x01\n\x14\x45xecuteActionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x18\n\x10\x61\x63tion_symbol_id\x18\x02 \x01(\t\x12\x37\n\x06inputs\x18\x03 \x03(\x0b\x32\'.sysml.ExecuteActionRequest.InputsEntry\x1a;\n\x0bInputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x15\x45xecuteActionResponse\x12:\n\x07outputs\x18\x01 \x03(\x0b\x32).sysml.ExecuteActionResponse.OutputsEntry\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a<\n\x0cOutputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"Z\n\x13\x45xecuteStateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x17state_machine_symbol_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65vents\x18\x03 \x03(\t\"\xee\x01\n\x14\x45xecuteStateResponse\x12\x16\n\x0estates_visited\x18\x01 \x03(\t\x12\x44\n\rfinal_context\x18\x02 \x03(\x0b\x32-.sysml.ExecuteStateResponse.FinalContextEntry\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a\x41\n\x11\x46inalContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xa0\x01\n\x0e\x43onvertRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x14\n\nmodel_hash\x18\x06 \x01(\tH\x00\x12\x13\n\x0b\x66rom_format\x18\x03 \x01(\t\x12\x11\n\tto_format\x18\x04 \x01(\t\x12\x1e\n\x16tolerate_syntax_errors\x18\x05 \x01(\x08\x42\x08\n\x06source\"\xb4\x01\n\x0f\x43onvertResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x13\n\x0b\x66rom_format\x18\x02 \x01(\t\x12\x11\n\tto_format\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x14\n\x0c\x65xperimental\x18\x06 \x01(\x08\x12\x1b\n\x13\x65xperimental_notice\x18\x07 \x01(\t\"Q\n\x11\x41pplyEditsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12(\n\noperations\x18\x02 \x03(\x0b\x32\x14.sysml.EditOperation\"\xbc\x01\n\rEditOperation\x12(\n\tset_value\x18\x01 \x01(\x0b\x32\x13.sysml.SetValueEditH\x00\x12#\n\x06rename\x18\x02 \x01(\x0b\x32\x11.sysml.RenameEditH\x00\x12*\n\nadd_member\x18\x03 \x01(\x0b\x32\x14.sysml.AddMemberEditH\x00\x12#\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x11.sysml.DeleteEditH\x00\x42\x0b\n\toperation\"\x82\x01\n\rAddMemberEdit\x12\r\n\x05owner\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\x14\n\x0cmultiplicity\x18\x05 \x01(\t\x12\r\n\x05value\x18\x06 \x01(\t\x12\x13\n\x0bspecializes\x18\x07 \x03(\t\"-\n\nDeleteEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61scade\x18\x02 \x01(\x08\"-\n\x0cSetValueEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\".\n\nRenameEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"\xc2\x01\n\x12\x41pplyEditsResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12#\n\x07\x61pplied\x18\x02 \x03(\x0b\x32\x12.sysml.AppliedEdit\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12#\n\x07\x66\x61ilure\x18\x04 \x01(\x0e\x32\x12.sysml.EditFailure\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x1a\n\x12referring_elements\x18\x06 \x03(\t\"z\n\x0b\x41ppliedEdit\x12\x17\n\x0foperation_index\x18\x01 \x01(\x05\x12\x0e\n\x06target\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x05\x12\x0e\n\x06length\x18\x04 \x01(\x05\x12\x10\n\x08old_text\x18\x05 \x01(\t\x12\x10\n\x08new_text\x18\x06 \x01(\t\"\xfd\x02\n\nSymbolInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04kind\x18\x03 \x01(\t\x12\x31\n\x08metadata\x18\x04 \x03(\x0b\x32\x1f.sysml.SymbolInfo.MetadataEntry\x12\x11\n\tchild_ids\x18\x05 \x03(\t\x12(\n\nattributes\x18\x06 \x03(\x0b\x32\x14.sysml.AttributeInfo\x12\"\n\ttype_info\x18\x07 \x01(\x0b\x32\x0f.sysml.TypeInfo\x12-\n\x0cmultiplicity\x18\x08 \x01(\x0b\x32\x17.sysml.MultiplicityInfo\x12.\n\x0fspecializations\x18\t \x03(\x0b\x32\x15.sysml.Specialization\x12#\n\x1bwithheld_library_attributes\x18\n \x01(\x05\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"X\n\x0eSpecialization\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x10\n\x08\x64\x65\x63lared\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t\x12\x13\n\x0btarget_kind\x18\x04 \x01(\t\"\x95\x01\n\x08TypeInfo\x12\x10\n\x08\x64\x65\x63lared\x18\x01 \x01(\t\x12\x13\n\x0bresolved_id\x18\x02 \x01(\t\x12\x15\n\rresolved_kind\x18\x03 \x01(\t\x12\x11\n\tprimitive\x18\x04 \x01(\t\x12\x18\n\x10primitive_source\x18\x05 \x01(\t\x12\x10\n\x08quantity\x18\x06 \x01(\x08\x12\x0c\n\x04unit\x18\x07 \x01(\t\"0\n\x10MultiplicityInfo\x12\r\n\x05lower\x18\x01 \x01(\t\x12\r\n\x05upper\x18\x02 \x01(\t\"V\n\rAttributeInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x1b\n\x05value\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x0c\n\x04unit\x18\x04 \x01(\t\"\xe2\x03\n\x05Value\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x02 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x03 \x01(\x08H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0binstance_id\x18\x05 \x01(\x03H\x00\x12(\n\x08sequence\x18\x06 \x01(\x0b\x32\x14.sysml.ValueSequenceH\x00\x12\x0e\n\x04null\x18\x07 \x01(\tH\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12*\n\x0c\x65num_literal\x18\t \x01(\x0b\x32\x12.sysml.EnumLiteralH\x00\x12\x0f\n\x05unset\x18\n \x01(\x08H\x00\x12!\n\x07\x63omplex\x18\x0b \x01(\x0b\x32\x0e.sysml.ComplexH\x00\x12\x1d\n\x05\x61rray\x18\x0c \x01(\x0b\x32\x0c.sysml.ArrayH\x00\x12\x1f\n\x06vector\x18\r \x01(\x0b\x32\r.sysml.VectorH\x00\x12\x30\n\x0fvector_quantity\x18\x0e \x01(\x0b\x32\x15.sysml.VectorQuantityH\x00\x12\x30\n\x0fmeasurement_ref\x18\x0f \x01(\x0b\x32\x15.sysml.MeasurementRefH\x00\x42\x06\n\x04kind\";\n\x05\x41rray\x12\x12\n\ndimensions\x18\x01 \x03(\x03\x12\x1e\n\x08\x65lements\x18\x02 \x03(\x0b\x32\x0c.sysml.Value\"*\n\x06Vector\x12 \n\ncomponents\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"5\n\x0eVectorQuantity\x12#\n\ncomponents\x18\x01 \x03(\x0b\x32\x0f.sysml.Quantity\"*\n\x07\x43omplex\x12\x0c\n\x04real\x18\x01 \x01(\x01\x12\x11\n\timaginary\x18\x02 \x01(\x01\"G\n\x0b\x45numLiteral\x12\x12\n\nliteral_id\x18\x01 \x01(\t\x12\x16\n\x0e\x65numeration_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\"/\n\rValueSequence\x12\x1e\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"|\n\x08Quantity\x12\x17\n\rint_magnitude\x18\x01 \x01(\x03H\x00\x12\x18\n\x0ereal_magnitude\x18\x02 \x01(\x01H\x00\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\"\n\tunit_term\x18\x04 \x01(\x0b\x32\x0f.sysml.UnitTermB\x0b\n\tmagnitude\"S\n\x0eMeasurementRef\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\"\n\tunit_term\x18\x02 \x01(\x0b\x32\x0f.sysml.UnitTerm\x12\x0f\n\x07unit_id\x18\x03 \x01(\t\"T\n\x08UnitTerm\x12\x11\n\tscale_num\x18\x01 \x01(\x01\x12\x11\n\tscale_den\x18\x02 \x01(\x01\x12\"\n\x07\x66\x61\x63tors\x18\x03 \x03(\x0b\x32\x11.sysml.UnitFactor\"/\n\nUnitFactor\x12\x0f\n\x07unit_id\x18\x01 \x01(\t\x12\x10\n\x08\x65xponent\x18\x02 \x01(\x01\"J\n\nDiagnostic\x12\x10\n\x08severity\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x04span\x18\x03 \x01(\x0b\x32\x0b.sysml.Span\"^\n\x04Span\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x12\n\nstart_line\x18\x02 \x01(\x05\x12\x11\n\tstart_col\x18\x03 \x01(\x05\x12\x10\n\x08\x65nd_line\x18\x04 \x01(\x05\x12\x0f\n\x07\x65nd_col\x18\x05 \x01(\x05\"\x13\n\x11ServerInfoRequest\";\n\x12ServerInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x02 \x03(\t\"S\n\x0cQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1b\n\x05query\x18\x02 \x01(\x0b\x32\x0c.sysml.Query\x12\x12\n\noslc_query\x18\x03 \x01(\t\"<\n\rQueryResponse\x12+\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x19.sysml.QueryResultElement\"H\n\x05Query\x12\r\n\x05scope\x18\x01 \x03(\t\x12\x0e\n\x06select\x18\x02 \x03(\t\x12 \n\x05where\x18\x03 \x01(\x0b\x32\x11.sysml.Constraint\"|\n\nConstraint\x12/\n\tprimitive\x18\x01 \x01(\x0b\x32\x1a.sysml.PrimitiveConstraintH\x00\x12/\n\tcomposite\x18\x02 \x01(\x0b\x32\x1a.sysml.CompositeConstraintH\x00\x42\x0c\n\nconstraint\"s\n\x13PrimitiveConstraint\x12\x0f\n\x07inverse\x18\x01 \x01(\x08\x12\x10\n\x08property\x18\x02 \x01(\t\x12*\n\x08operator\x18\x03 \x01(\x0e\x32\x18.sysml.PrimitiveOperator\x12\r\n\x05value\x18\x04 \x03(\t\"h\n\x13\x43ompositeConstraint\x12*\n\x08operator\x18\x01 \x01(\x0e\x32\x18.sysml.CompositeOperator\x12%\n\nconstraint\x18\x02 \x03(\x0b\x32\x11.sysml.Constraint\"\xa0\x01\n\x12QueryResultElement\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12=\n\nproperties\x18\x03 \x03(\x0b\x32).sysml.QueryResultElement.PropertiesEntry\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"s\n\nSweepRange\x12\x11\n\tparameter\x18\x01 \x01(\t\x12\x1b\n\x05start\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x19\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x1a\n\x04step\x18\x04 \x01(\x0b\x32\x0c.sysml.Value\"\xc0\x02\n\x0fRunSweepRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x43\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32*.sysml.RunSweepRequest.NamedArgumentsEntry\x12!\n\x06ranges\x18\x06 \x03(\x0b\x32\x11.sysml.SweepRange\x12\x0f\n\x07samples\x18\x07 \x01(\x03\x12\x0c\n\x04seed\x18\x08 \x01(\x04\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x08SweepRow\x12!\n\x06inputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x03 \x03(\x0b\x32\x0e.sysml.Verdict\x12\x16\n\x0e\x65lapsed_micros\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\"\xed\x01\n\x10RunSweepResponse\x12\x1d\n\x04rows\x18\x01 \x03(\x0b\x32\x0f.sysml.SweepRow\x12\x12\n\nparameters\x18\x02 \x03(\t\x12\x0f\n\x07sampled\x18\x03 \x01(\x08\x12\x0c\n\x04seed\x18\x04 \x01(\x04\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x06 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x07 \x01(\x0e\x32\x14.sysml.FailureReason\x12\"\n\tinstances\x18\x08 \x03(\x0b\x32\x0f.sysml.Instance\"n\n\x17RunDocumentQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x10\n\x08query_id\x18\x02 \x01(\t\x12-\n\x08\x62indings\x18\x03 \x03(\x0b\x32\x1b.sysml.DocumentQueryBinding\"O\n\x14\x44ocumentQueryBinding\x12\x11\n\tparameter\x18\x01 \x01(\t\x12$\n\x06values\x18\x02 \x03(\x0b\x32\x14.sysml.DocumentValue\"\xd5\x01\n\rDocumentValue\x12\x14\n\nelement_id\x18\x01 \x01(\tH\x00\x12\x16\n\x0cstring_value\x18\x02 \x01(\tH\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x04 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x05 \x01(\x08H\x00\x12\x12\n\x08infinity\x18\x06 \x01(\x08H\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12\x14\n\x0c\x65lement_type\x18\x07 \x01(\tB\x06\n\x04kind\"#\n\x13\x44ocumentQueryColumn\x12\x0c\n\x04name\x18\x01 \x01(\t\"9\n\x11\x44ocumentQueryCell\x12$\n\x06values\x18\x01 \x03(\x0b\x32\x14.sysml.DocumentValue\"b\n\x10\x44ocumentQueryRow\x12%\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x14.sysml.DocumentValue\x12\'\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32\x18.sysml.DocumentQueryCell\"n\n\x18RunDocumentQueryResponse\x12+\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x1a.sysml.DocumentQueryColumn\x12%\n\x04rows\x18\x02 \x03(\x0b\x32\x17.sysml.DocumentQueryRow\"@\n\x15RenderDocumentRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\t\"*\n\x16RenderDocumentResponse\x12\x10\n\x08markdown\x18\x01 \x01(\t*\x93\x01\n\rFailureReason\x12\x1e\n\x1a\x46\x41ILURE_REASON_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x46\x41ILURE_REASON_EVALUATION\x10\x01\x12\x1d\n\x19\x46\x41ILURE_REASON_WRONG_KIND\x10\x02\x12$\n FAILURE_REASON_AMBIGUOUS_SUBJECT\x10\x03*\x9d\x04\n\x0b\x45\x64itFailure\x12\x1c\n\x18\x45\x44IT_FAILURE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x45\x44IT_FAILURE_NO_OPERATIONS\x10\x01\x12\x1f\n\x1b\x45\x44IT_FAILURE_UNKNOWN_TARGET\x10\x02\x12!\n\x1d\x45\x44IT_FAILURE_AMBIGUOUS_TARGET\x10\x03\x12\x1b\n\x17\x45\x44IT_FAILURE_NOT_VALUED\x10\x04\x12\x1e\n\x1a\x45\x44IT_FAILURE_INVALID_VALUE\x10\x05\x12\x1d\n\x19\x45\x44IT_FAILURE_INVALID_NAME\x10\x06\x12\x1a\n\x16\x45\x44IT_FAILURE_NOT_NAMED\x10\x07\x12\"\n\x1e\x45\x44IT_FAILURE_RENAME_REFERENCED\x10\x08\x12\"\n\x1e\x45\x44IT_FAILURE_OVERLAPPING_EDITS\x10\t\x12\x1f\n\x1b\x45\x44IT_FAILURE_RESULT_INVALID\x10\n\x12\x1e\n\x1a\x45\x44IT_FAILURE_OWNER_UNKNOWN\x10\x0b\x12$\n EDIT_FAILURE_OWNER_NOT_NAMESPACE\x10\x0c\x12\x1d\n\x19\x45\x44IT_FAILURE_ILLEGAL_KIND\x10\r\x12\"\n\x1e\x45\x44IT_FAILURE_MEMBER_NAME_TAKEN\x10\x0e\x12\"\n\x1e\x45\x44IT_FAILURE_DELETE_REFERENCED\x10\x0f*\x92\x01\n\x11PrimitiveOperator\x12\"\n\x1ePRIMITIVE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1c\n\x18PRIMITIVE_OPERATOR_EQUAL\x10\x01\x12\x1e\n\x1aPRIMITIVE_OPERATOR_GREATER\x10\x02\x12\x1b\n\x17PRIMITIVE_OPERATOR_LESS\x10\x03*n\n\x11\x43ompositeOperator\x12\"\n\x1e\x43OMPOSITE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43OMPOSITE_OPERATOR_AND\x10\x01\x12\x19\n\x15\x43OMPOSITE_OPERATOR_OR\x10\x02\x32\xa4\x0b\n\x0cSysMLService\x12\x44\n\rGetServerInfo\x12\x18.sysml.ServerInfoRequest\x1a\x19.sysml.ServerInfoResponse\x12>\n\tParseFile\x12\x17.sysml.ParseFileRequest\x1a\x18.sysml.ParseFileResponse\x12G\n\x0cParseSources\x12\x1a.sysml.ParseSourcesRequest\x1a\x1b.sysml.ParseSourcesResponse\x12;\n\tGetSymbol\x12\x17.sysml.GetSymbolRequest\x1a\x15.sysml.SymbolResponse\x12G\n\x0eGetDiagnostics\x12\x19.sysml.DiagnosticsRequest\x1a\x1a.sysml.DiagnosticsResponse\x12;\n\x08\x45valuate\x12\x16.sysml.EvaluateRequest\x1a\x17.sysml.EvaluateResponse\x12\x44\n\x0bInstantiate\x12\x19.sysml.InstantiateRequest\x1a\x1a.sysml.InstantiateResponse\x12J\n\rExecuteAction\x12\x1b.sysml.ExecuteActionRequest\x1a\x1c.sysml.ExecuteActionResponse\x12G\n\x0c\x45xecuteState\x12\x1a.sysml.ExecuteStateRequest\x1a\x1b.sysml.ExecuteStateResponse\x12\x38\n\x07\x43onvert\x12\x15.sysml.ConvertRequest\x1a\x16.sysml.ConvertResponse\x12\x41\n\nApplyEdits\x12\x18.sysml.ApplyEditsRequest\x1a\x19.sysml.ApplyEditsResponse\x12S\n\x10VerifyConstraint\x12\x1e.sysml.VerifyConstraintRequest\x1a\x1f.sysml.VerifyConstraintResponse\x12V\n\x11VerifyRequirement\x12\x1f.sysml.VerifyRequirementRequest\x1a .sysml.VerifyRequirementResponse\x12Y\n\x12VerifySatisfaction\x12 .sysml.VerifySatisfactionRequest\x1a!.sysml.VerifySatisfactionResponse\x12G\n\x0c\x45valuateCalc\x12\x1a.sysml.EvaluateCalcRequest\x1a\x1b.sysml.EvaluateCalcResponse\x12\x44\n\x0bRunAnalysis\x12\x19.sysml.RunAnalysisRequest\x1a\x1a.sysml.RunAnalysisResponse\x12;\n\x08RunSweep\x12\x16.sysml.RunSweepRequest\x1a\x17.sysml.RunSweepResponse\x12\x32\n\x05Query\x12\x13.sysml.QueryRequest\x1a\x14.sysml.QueryResponse\x12S\n\x10RunDocumentQuery\x12\x1e.sysml.RunDocumentQueryRequest\x1a\x1f.sysml.RunDocumentQueryResponse\x12M\n\x0eRenderDocument\x12\x1c.sysml.RenderDocumentRequest\x1a\x1d.sysml.RenderDocumentResponseB*Z(github.com/Open-MBEE/OpenSysML/api/protob\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bsysml.proto\x12\x05sysml\"\xe2\x01\n\x07Verdict\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x12\n\nelement_id\x18\x02 \x01(\t\x12\x0f\n\x07\x65lement\x18\x03 \x01(\t\x12\r\n\x05holds\x18\x04 \x01(\x08\x12\x11\n\tcondition\x18\x05 \x01(\t\x12\x13\n\x0binstance_id\x18\x06 \x01(\x03\x12\x18\n\x10instance_type_id\x18\x07 \x01(\t\x12\r\n\x05\x65rror\x18\x08 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\t \x01(\x0e\x32\x14.sysml.FailureReason\x12\x16\n\x0erequirement_id\x18\n \x01(\t\"[\n\x17VerifyConstraintRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"\x96\x01\n\x18VerifyConstraintResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\"\\\n\x18VerifyRequirementRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"m\n\x13VerificationVerdict\x12\x0f\n\x07\x63\x61se_id\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65tail\x18\x03 \x01(\t\x12\x0f\n\x07subcase\x18\x04 \x01(\x08\x12\x16\n\x0erequirement_id\x18\x05 \x01(\t\"\xd2\x01\n\x19VerifyRequirementResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x39\n\x15verification_verdicts\x18\x05 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"B\n\x19VerifySatisfactionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x82\x02\n\x1aVerifySatisfactionResponse\x12 \n\x08verdicts\x18\x01 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x06 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"]\n\x13\x45valuateCalcRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x1f\n\targuments\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\"\xbd\x01\n\x14\x45valuateCalcResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\"7\n\nCalcOutput\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\"\x84\x02\n\x12RunAnalysisRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x46\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32-.sysml.RunAnalysisRequest.NamedArgumentsEntry\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\x9f\x02\n\x13RunAnalysisResponse\x12\"\n\x07outputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x02 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x03 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x07 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"\x8c\x01\n\x10ParseFileRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x18\n\x0c\x63ontent_hash\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08language\x18\x04 \x01(\t\x12\x1a\n\x12strict_conformance\x18\x05 \x01(\x08\x42\x08\n\x06source\"b\n\x0eSourceDocument\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x10\n\x08language\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\tB\x08\n\x06source\"[\n\x13ParseSourcesRequest\x12(\n\tdocuments\x18\x01 \x03(\x0b\x32\x15.sysml.SourceDocument\x12\x1a\n\x12strict_conformance\x18\x02 \x01(\x08\"\x83\x01\n\x14ParseSourcesResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12 \n\x05roots\x18\x02 \x03(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\x7f\n\x11ParseFileResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x04root\x18\x02 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"9\n\x10GetSymbolRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"B\n\x0eSymbolResponse\x12!\n\x06symbol\x18\x01 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"(\n\x12\x44iagnosticsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\"L\n\x13\x44iagnosticsResponse\x12&\n\x0b\x64iagnostics\x18\x01 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"o\n\x0f\x45valuateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x12\n\nexpression\x18\x02 \x01(\t\x12\x19\n\x11\x63ontext_symbol_id\x18\x03 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x04 \x01(\t\"g\n\x10\x45valuateResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\"\xc2\x01\n\x08Instance\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x16\n\x0etype_symbol_id\x18\x02 \x01(\t\x12:\n\x0e\x66\x65\x61ture_values\x18\x04 \x03(\x0b\x32\".sysml.Instance.FeatureValuesEntry\x1aI\n\x12\x46\x65\x61tureValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.sysml.FeatureValue:\x02\x38\x01J\x04\x08\x03\x10\x04R\x05slots\"\x84\x01\n\x0c\x46\x65\x61tureValue\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\x12\x14\n\x0cmaterialized\x18\x04 \x01(\x08\x12\r\n\x05\x65rror\x18\x05 \x01(\t\";\n\x12InstantiateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x93\x01\n\x13InstantiateResponse\x12!\n\x08instance\x18\x01 \x01(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\"\n\tinstances\x18\x04 \x03(\x0b\x32\x0f.sysml.Instance\"\xba\x01\n\x14\x45xecuteActionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x18\n\x10\x61\x63tion_symbol_id\x18\x02 \x01(\t\x12\x37\n\x06inputs\x18\x03 \x03(\x0b\x32\'.sysml.ExecuteActionRequest.InputsEntry\x1a;\n\x0bInputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x15\x45xecuteActionResponse\x12:\n\x07outputs\x18\x01 \x03(\x0b\x32).sysml.ExecuteActionResponse.OutputsEntry\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a<\n\x0cOutputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"Z\n\x13\x45xecuteStateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x17state_machine_symbol_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65vents\x18\x03 \x03(\t\"\xee\x01\n\x14\x45xecuteStateResponse\x12\x16\n\x0estates_visited\x18\x01 \x03(\t\x12\x44\n\rfinal_context\x18\x02 \x03(\x0b\x32-.sysml.ExecuteStateResponse.FinalContextEntry\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a\x41\n\x11\x46inalContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xa0\x01\n\x0e\x43onvertRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x14\n\nmodel_hash\x18\x06 \x01(\tH\x00\x12\x13\n\x0b\x66rom_format\x18\x03 \x01(\t\x12\x11\n\tto_format\x18\x04 \x01(\t\x12\x1e\n\x16tolerate_syntax_errors\x18\x05 \x01(\x08\x42\x08\n\x06source\"\xb4\x01\n\x0f\x43onvertResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x13\n\x0b\x66rom_format\x18\x02 \x01(\t\x12\x11\n\tto_format\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x14\n\x0c\x65xperimental\x18\x06 \x01(\x08\x12\x1b\n\x13\x65xperimental_notice\x18\x07 \x01(\t\"Q\n\x11\x41pplyEditsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12(\n\noperations\x18\x02 \x03(\x0b\x32\x14.sysml.EditOperation\"\xbc\x01\n\rEditOperation\x12(\n\tset_value\x18\x01 \x01(\x0b\x32\x13.sysml.SetValueEditH\x00\x12#\n\x06rename\x18\x02 \x01(\x0b\x32\x11.sysml.RenameEditH\x00\x12*\n\nadd_member\x18\x03 \x01(\x0b\x32\x14.sysml.AddMemberEditH\x00\x12#\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x11.sysml.DeleteEditH\x00\x42\x0b\n\toperation\"\x82\x01\n\rAddMemberEdit\x12\r\n\x05owner\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\x14\n\x0cmultiplicity\x18\x05 \x01(\t\x12\r\n\x05value\x18\x06 \x01(\t\x12\x13\n\x0bspecializes\x18\x07 \x03(\t\"-\n\nDeleteEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61scade\x18\x02 \x01(\x08\"-\n\x0cSetValueEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\".\n\nRenameEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"\xc2\x01\n\x12\x41pplyEditsResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12#\n\x07\x61pplied\x18\x02 \x03(\x0b\x32\x12.sysml.AppliedEdit\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12#\n\x07\x66\x61ilure\x18\x04 \x01(\x0e\x32\x12.sysml.EditFailure\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x1a\n\x12referring_elements\x18\x06 \x03(\t\"z\n\x0b\x41ppliedEdit\x12\x17\n\x0foperation_index\x18\x01 \x01(\x05\x12\x0e\n\x06target\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x05\x12\x0e\n\x06length\x18\x04 \x01(\x05\x12\x10\n\x08old_text\x18\x05 \x01(\t\x12\x10\n\x08new_text\x18\x06 \x01(\t\"\xfd\x02\n\nSymbolInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04kind\x18\x03 \x01(\t\x12\x31\n\x08metadata\x18\x04 \x03(\x0b\x32\x1f.sysml.SymbolInfo.MetadataEntry\x12\x11\n\tchild_ids\x18\x05 \x03(\t\x12(\n\nattributes\x18\x06 \x03(\x0b\x32\x14.sysml.AttributeInfo\x12\"\n\ttype_info\x18\x07 \x01(\x0b\x32\x0f.sysml.TypeInfo\x12-\n\x0cmultiplicity\x18\x08 \x01(\x0b\x32\x17.sysml.MultiplicityInfo\x12.\n\x0fspecializations\x18\t \x03(\x0b\x32\x15.sysml.Specialization\x12#\n\x1bwithheld_library_attributes\x18\n \x01(\x05\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"X\n\x0eSpecialization\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x10\n\x08\x64\x65\x63lared\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t\x12\x13\n\x0btarget_kind\x18\x04 \x01(\t\"\x95\x01\n\x08TypeInfo\x12\x10\n\x08\x64\x65\x63lared\x18\x01 \x01(\t\x12\x13\n\x0bresolved_id\x18\x02 \x01(\t\x12\x15\n\rresolved_kind\x18\x03 \x01(\t\x12\x11\n\tprimitive\x18\x04 \x01(\t\x12\x18\n\x10primitive_source\x18\x05 \x01(\t\x12\x10\n\x08quantity\x18\x06 \x01(\x08\x12\x0c\n\x04unit\x18\x07 \x01(\t\"0\n\x10MultiplicityInfo\x12\r\n\x05lower\x18\x01 \x01(\t\x12\r\n\x05upper\x18\x02 \x01(\t\"V\n\rAttributeInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x1b\n\x05value\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x0c\n\x04unit\x18\x04 \x01(\t\"\xf6\x03\n\x05Value\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x02 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x03 \x01(\x08H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0binstance_id\x18\x05 \x01(\x03H\x00\x12(\n\x08sequence\x18\x06 \x01(\x0b\x32\x14.sysml.ValueSequenceH\x00\x12\x0e\n\x04null\x18\x07 \x01(\tH\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12*\n\x0c\x65num_literal\x18\t \x01(\x0b\x32\x12.sysml.EnumLiteralH\x00\x12\x0f\n\x05unset\x18\n \x01(\x08H\x00\x12!\n\x07\x63omplex\x18\x0b \x01(\x0b\x32\x0e.sysml.ComplexH\x00\x12\x1d\n\x05\x61rray\x18\x0c \x01(\x0b\x32\x0c.sysml.ArrayH\x00\x12\x1f\n\x06vector\x18\r \x01(\x0b\x32\r.sysml.VectorH\x00\x12\x30\n\x0fvector_quantity\x18\x0e \x01(\x0b\x32\x15.sysml.VectorQuantityH\x00\x12\x30\n\x0fmeasurement_ref\x18\x0f \x01(\x0b\x32\x15.sysml.MeasurementRefH\x00\x12\x12\n\x08infinity\x18\x10 \x01(\x08H\x00\x42\x06\n\x04kind\";\n\x05\x41rray\x12\x12\n\ndimensions\x18\x01 \x03(\x03\x12\x1e\n\x08\x65lements\x18\x02 \x03(\x0b\x32\x0c.sysml.Value\"*\n\x06Vector\x12 \n\ncomponents\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"5\n\x0eVectorQuantity\x12#\n\ncomponents\x18\x01 \x03(\x0b\x32\x0f.sysml.Quantity\"*\n\x07\x43omplex\x12\x0c\n\x04real\x18\x01 \x01(\x01\x12\x11\n\timaginary\x18\x02 \x01(\x01\"G\n\x0b\x45numLiteral\x12\x12\n\nliteral_id\x18\x01 \x01(\t\x12\x16\n\x0e\x65numeration_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\"/\n\rValueSequence\x12\x1e\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"|\n\x08Quantity\x12\x17\n\rint_magnitude\x18\x01 \x01(\x03H\x00\x12\x18\n\x0ereal_magnitude\x18\x02 \x01(\x01H\x00\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\"\n\tunit_term\x18\x04 \x01(\x0b\x32\x0f.sysml.UnitTermB\x0b\n\tmagnitude\"S\n\x0eMeasurementRef\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\"\n\tunit_term\x18\x02 \x01(\x0b\x32\x0f.sysml.UnitTerm\x12\x0f\n\x07unit_id\x18\x03 \x01(\t\"T\n\x08UnitTerm\x12\x11\n\tscale_num\x18\x01 \x01(\x01\x12\x11\n\tscale_den\x18\x02 \x01(\x01\x12\"\n\x07\x66\x61\x63tors\x18\x03 \x03(\x0b\x32\x11.sysml.UnitFactor\"/\n\nUnitFactor\x12\x0f\n\x07unit_id\x18\x01 \x01(\t\x12\x10\n\x08\x65xponent\x18\x02 \x01(\x01\"J\n\nDiagnostic\x12\x10\n\x08severity\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x04span\x18\x03 \x01(\x0b\x32\x0b.sysml.Span\"^\n\x04Span\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x12\n\nstart_line\x18\x02 \x01(\x05\x12\x11\n\tstart_col\x18\x03 \x01(\x05\x12\x10\n\x08\x65nd_line\x18\x04 \x01(\x05\x12\x0f\n\x07\x65nd_col\x18\x05 \x01(\x05\"\x13\n\x11ServerInfoRequest\";\n\x12ServerInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x02 \x03(\t\"S\n\x0cQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1b\n\x05query\x18\x02 \x01(\x0b\x32\x0c.sysml.Query\x12\x12\n\noslc_query\x18\x03 \x01(\t\"<\n\rQueryResponse\x12+\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x19.sysml.QueryResultElement\"H\n\x05Query\x12\r\n\x05scope\x18\x01 \x03(\t\x12\x0e\n\x06select\x18\x02 \x03(\t\x12 \n\x05where\x18\x03 \x01(\x0b\x32\x11.sysml.Constraint\"|\n\nConstraint\x12/\n\tprimitive\x18\x01 \x01(\x0b\x32\x1a.sysml.PrimitiveConstraintH\x00\x12/\n\tcomposite\x18\x02 \x01(\x0b\x32\x1a.sysml.CompositeConstraintH\x00\x42\x0c\n\nconstraint\"s\n\x13PrimitiveConstraint\x12\x0f\n\x07inverse\x18\x01 \x01(\x08\x12\x10\n\x08property\x18\x02 \x01(\t\x12*\n\x08operator\x18\x03 \x01(\x0e\x32\x18.sysml.PrimitiveOperator\x12\r\n\x05value\x18\x04 \x03(\t\"h\n\x13\x43ompositeConstraint\x12*\n\x08operator\x18\x01 \x01(\x0e\x32\x18.sysml.CompositeOperator\x12%\n\nconstraint\x18\x02 \x03(\x0b\x32\x11.sysml.Constraint\"\xa0\x01\n\x12QueryResultElement\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12=\n\nproperties\x18\x03 \x03(\x0b\x32).sysml.QueryResultElement.PropertiesEntry\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"s\n\nSweepRange\x12\x11\n\tparameter\x18\x01 \x01(\t\x12\x1b\n\x05start\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x19\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x1a\n\x04step\x18\x04 \x01(\x0b\x32\x0c.sysml.Value\"\xc0\x02\n\x0fRunSweepRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x43\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32*.sysml.RunSweepRequest.NamedArgumentsEntry\x12!\n\x06ranges\x18\x06 \x03(\x0b\x32\x11.sysml.SweepRange\x12\x0f\n\x07samples\x18\x07 \x01(\x03\x12\x0c\n\x04seed\x18\x08 \x01(\x04\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x08SweepRow\x12!\n\x06inputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x03 \x03(\x0b\x32\x0e.sysml.Verdict\x12\x16\n\x0e\x65lapsed_micros\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\"\xed\x01\n\x10RunSweepResponse\x12\x1d\n\x04rows\x18\x01 \x03(\x0b\x32\x0f.sysml.SweepRow\x12\x12\n\nparameters\x18\x02 \x03(\t\x12\x0f\n\x07sampled\x18\x03 \x01(\x08\x12\x0c\n\x04seed\x18\x04 \x01(\x04\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x06 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x07 \x01(\x0e\x32\x14.sysml.FailureReason\x12\"\n\tinstances\x18\x08 \x03(\x0b\x32\x0f.sysml.Instance\"n\n\x17RunDocumentQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x10\n\x08query_id\x18\x02 \x01(\t\x12-\n\x08\x62indings\x18\x03 \x03(\x0b\x32\x1b.sysml.DocumentQueryBinding\"O\n\x14\x44ocumentQueryBinding\x12\x11\n\tparameter\x18\x01 \x01(\t\x12$\n\x06values\x18\x02 \x03(\x0b\x32\x14.sysml.DocumentValue\"\xd5\x01\n\rDocumentValue\x12\x14\n\nelement_id\x18\x01 \x01(\tH\x00\x12\x16\n\x0cstring_value\x18\x02 \x01(\tH\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x04 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x05 \x01(\x08H\x00\x12\x12\n\x08infinity\x18\x06 \x01(\x08H\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12\x14\n\x0c\x65lement_type\x18\x07 \x01(\tB\x06\n\x04kind\"#\n\x13\x44ocumentQueryColumn\x12\x0c\n\x04name\x18\x01 \x01(\t\"9\n\x11\x44ocumentQueryCell\x12$\n\x06values\x18\x01 \x03(\x0b\x32\x14.sysml.DocumentValue\"b\n\x10\x44ocumentQueryRow\x12%\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x14.sysml.DocumentValue\x12\'\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32\x18.sysml.DocumentQueryCell\"n\n\x18RunDocumentQueryResponse\x12+\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x1a.sysml.DocumentQueryColumn\x12%\n\x04rows\x18\x02 \x03(\x0b\x32\x17.sysml.DocumentQueryRow\"@\n\x15RenderDocumentRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\t\"*\n\x16RenderDocumentResponse\x12\x10\n\x08markdown\x18\x01 \x01(\t*\x93\x01\n\rFailureReason\x12\x1e\n\x1a\x46\x41ILURE_REASON_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x46\x41ILURE_REASON_EVALUATION\x10\x01\x12\x1d\n\x19\x46\x41ILURE_REASON_WRONG_KIND\x10\x02\x12$\n FAILURE_REASON_AMBIGUOUS_SUBJECT\x10\x03*\x9d\x04\n\x0b\x45\x64itFailure\x12\x1c\n\x18\x45\x44IT_FAILURE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x45\x44IT_FAILURE_NO_OPERATIONS\x10\x01\x12\x1f\n\x1b\x45\x44IT_FAILURE_UNKNOWN_TARGET\x10\x02\x12!\n\x1d\x45\x44IT_FAILURE_AMBIGUOUS_TARGET\x10\x03\x12\x1b\n\x17\x45\x44IT_FAILURE_NOT_VALUED\x10\x04\x12\x1e\n\x1a\x45\x44IT_FAILURE_INVALID_VALUE\x10\x05\x12\x1d\n\x19\x45\x44IT_FAILURE_INVALID_NAME\x10\x06\x12\x1a\n\x16\x45\x44IT_FAILURE_NOT_NAMED\x10\x07\x12\"\n\x1e\x45\x44IT_FAILURE_RENAME_REFERENCED\x10\x08\x12\"\n\x1e\x45\x44IT_FAILURE_OVERLAPPING_EDITS\x10\t\x12\x1f\n\x1b\x45\x44IT_FAILURE_RESULT_INVALID\x10\n\x12\x1e\n\x1a\x45\x44IT_FAILURE_OWNER_UNKNOWN\x10\x0b\x12$\n EDIT_FAILURE_OWNER_NOT_NAMESPACE\x10\x0c\x12\x1d\n\x19\x45\x44IT_FAILURE_ILLEGAL_KIND\x10\r\x12\"\n\x1e\x45\x44IT_FAILURE_MEMBER_NAME_TAKEN\x10\x0e\x12\"\n\x1e\x45\x44IT_FAILURE_DELETE_REFERENCED\x10\x0f*\x92\x01\n\x11PrimitiveOperator\x12\"\n\x1ePRIMITIVE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1c\n\x18PRIMITIVE_OPERATOR_EQUAL\x10\x01\x12\x1e\n\x1aPRIMITIVE_OPERATOR_GREATER\x10\x02\x12\x1b\n\x17PRIMITIVE_OPERATOR_LESS\x10\x03*n\n\x11\x43ompositeOperator\x12\"\n\x1e\x43OMPOSITE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43OMPOSITE_OPERATOR_AND\x10\x01\x12\x19\n\x15\x43OMPOSITE_OPERATOR_OR\x10\x02\x32\xa4\x0b\n\x0cSysMLService\x12\x44\n\rGetServerInfo\x12\x18.sysml.ServerInfoRequest\x1a\x19.sysml.ServerInfoResponse\x12>\n\tParseFile\x12\x17.sysml.ParseFileRequest\x1a\x18.sysml.ParseFileResponse\x12G\n\x0cParseSources\x12\x1a.sysml.ParseSourcesRequest\x1a\x1b.sysml.ParseSourcesResponse\x12;\n\tGetSymbol\x12\x17.sysml.GetSymbolRequest\x1a\x15.sysml.SymbolResponse\x12G\n\x0eGetDiagnostics\x12\x19.sysml.DiagnosticsRequest\x1a\x1a.sysml.DiagnosticsResponse\x12;\n\x08\x45valuate\x12\x16.sysml.EvaluateRequest\x1a\x17.sysml.EvaluateResponse\x12\x44\n\x0bInstantiate\x12\x19.sysml.InstantiateRequest\x1a\x1a.sysml.InstantiateResponse\x12J\n\rExecuteAction\x12\x1b.sysml.ExecuteActionRequest\x1a\x1c.sysml.ExecuteActionResponse\x12G\n\x0c\x45xecuteState\x12\x1a.sysml.ExecuteStateRequest\x1a\x1b.sysml.ExecuteStateResponse\x12\x38\n\x07\x43onvert\x12\x15.sysml.ConvertRequest\x1a\x16.sysml.ConvertResponse\x12\x41\n\nApplyEdits\x12\x18.sysml.ApplyEditsRequest\x1a\x19.sysml.ApplyEditsResponse\x12S\n\x10VerifyConstraint\x12\x1e.sysml.VerifyConstraintRequest\x1a\x1f.sysml.VerifyConstraintResponse\x12V\n\x11VerifyRequirement\x12\x1f.sysml.VerifyRequirementRequest\x1a .sysml.VerifyRequirementResponse\x12Y\n\x12VerifySatisfaction\x12 .sysml.VerifySatisfactionRequest\x1a!.sysml.VerifySatisfactionResponse\x12G\n\x0c\x45valuateCalc\x12\x1a.sysml.EvaluateCalcRequest\x1a\x1b.sysml.EvaluateCalcResponse\x12\x44\n\x0bRunAnalysis\x12\x19.sysml.RunAnalysisRequest\x1a\x1a.sysml.RunAnalysisResponse\x12;\n\x08RunSweep\x12\x16.sysml.RunSweepRequest\x1a\x17.sysml.RunSweepResponse\x12\x32\n\x05Query\x12\x13.sysml.QueryRequest\x1a\x14.sysml.QueryResponse\x12S\n\x10RunDocumentQuery\x12\x1e.sysml.RunDocumentQueryRequest\x1a\x1f.sysml.RunDocumentQueryResponse\x12M\n\x0eRenderDocument\x12\x1c.sysml.RenderDocumentRequest\x1a\x1d.sysml.RenderDocumentResponseB*Z(github.com/Open-MBEE/OpenSysML/api/protob\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -50,14 +50,14 @@ _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_options = b'8\001' _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._loaded_options = None _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_options = b'8\001' - _globals['_FAILUREREASON']._serialized_start=10308 - _globals['_FAILUREREASON']._serialized_end=10455 - _globals['_EDITFAILURE']._serialized_start=10458 - _globals['_EDITFAILURE']._serialized_end=10999 - _globals['_PRIMITIVEOPERATOR']._serialized_start=11002 - _globals['_PRIMITIVEOPERATOR']._serialized_end=11148 - _globals['_COMPOSITEOPERATOR']._serialized_start=11150 - _globals['_COMPOSITEOPERATOR']._serialized_end=11260 + _globals['_FAILUREREASON']._serialized_start=10328 + _globals['_FAILUREREASON']._serialized_end=10475 + _globals['_EDITFAILURE']._serialized_start=10478 + _globals['_EDITFAILURE']._serialized_end=11019 + _globals['_PRIMITIVEOPERATOR']._serialized_start=11022 + _globals['_PRIMITIVEOPERATOR']._serialized_end=11168 + _globals['_COMPOSITEOPERATOR']._serialized_start=11170 + _globals['_COMPOSITEOPERATOR']._serialized_end=11280 _globals['_VERDICT']._serialized_start=23 _globals['_VERDICT']._serialized_end=249 _globals['_VERIFYCONSTRAINTREQUEST']._serialized_start=251 @@ -165,79 +165,79 @@ _globals['_ATTRIBUTEINFO']._serialized_start=6365 _globals['_ATTRIBUTEINFO']._serialized_end=6451 _globals['_VALUE']._serialized_start=6454 - _globals['_VALUE']._serialized_end=6936 - _globals['_ARRAY']._serialized_start=6938 - _globals['_ARRAY']._serialized_end=6997 - _globals['_VECTOR']._serialized_start=6999 - _globals['_VECTOR']._serialized_end=7041 - _globals['_VECTORQUANTITY']._serialized_start=7043 - _globals['_VECTORQUANTITY']._serialized_end=7096 - _globals['_COMPLEX']._serialized_start=7098 - _globals['_COMPLEX']._serialized_end=7140 - _globals['_ENUMLITERAL']._serialized_start=7142 - _globals['_ENUMLITERAL']._serialized_end=7213 - _globals['_VALUESEQUENCE']._serialized_start=7215 - _globals['_VALUESEQUENCE']._serialized_end=7262 - _globals['_QUANTITY']._serialized_start=7264 - _globals['_QUANTITY']._serialized_end=7388 - _globals['_MEASUREMENTREF']._serialized_start=7390 - _globals['_MEASUREMENTREF']._serialized_end=7473 - _globals['_UNITTERM']._serialized_start=7475 - _globals['_UNITTERM']._serialized_end=7559 - _globals['_UNITFACTOR']._serialized_start=7561 - _globals['_UNITFACTOR']._serialized_end=7608 - _globals['_DIAGNOSTIC']._serialized_start=7610 - _globals['_DIAGNOSTIC']._serialized_end=7684 - _globals['_SPAN']._serialized_start=7686 - _globals['_SPAN']._serialized_end=7780 - _globals['_SERVERINFOREQUEST']._serialized_start=7782 - _globals['_SERVERINFOREQUEST']._serialized_end=7801 - _globals['_SERVERINFORESPONSE']._serialized_start=7803 - _globals['_SERVERINFORESPONSE']._serialized_end=7862 - _globals['_QUERYREQUEST']._serialized_start=7864 - _globals['_QUERYREQUEST']._serialized_end=7947 - _globals['_QUERYRESPONSE']._serialized_start=7949 - _globals['_QUERYRESPONSE']._serialized_end=8009 - _globals['_QUERY']._serialized_start=8011 - _globals['_QUERY']._serialized_end=8083 - _globals['_CONSTRAINT']._serialized_start=8085 - _globals['_CONSTRAINT']._serialized_end=8209 - _globals['_PRIMITIVECONSTRAINT']._serialized_start=8211 - _globals['_PRIMITIVECONSTRAINT']._serialized_end=8326 - _globals['_COMPOSITECONSTRAINT']._serialized_start=8328 - _globals['_COMPOSITECONSTRAINT']._serialized_end=8432 - _globals['_QUERYRESULTELEMENT']._serialized_start=8435 - _globals['_QUERYRESULTELEMENT']._serialized_end=8595 - _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_start=8546 - _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_end=8595 - _globals['_SWEEPRANGE']._serialized_start=8597 - _globals['_SWEEPRANGE']._serialized_end=8712 - _globals['_RUNSWEEPREQUEST']._serialized_start=8715 - _globals['_RUNSWEEPREQUEST']._serialized_end=9035 + _globals['_VALUE']._serialized_end=6956 + _globals['_ARRAY']._serialized_start=6958 + _globals['_ARRAY']._serialized_end=7017 + _globals['_VECTOR']._serialized_start=7019 + _globals['_VECTOR']._serialized_end=7061 + _globals['_VECTORQUANTITY']._serialized_start=7063 + _globals['_VECTORQUANTITY']._serialized_end=7116 + _globals['_COMPLEX']._serialized_start=7118 + _globals['_COMPLEX']._serialized_end=7160 + _globals['_ENUMLITERAL']._serialized_start=7162 + _globals['_ENUMLITERAL']._serialized_end=7233 + _globals['_VALUESEQUENCE']._serialized_start=7235 + _globals['_VALUESEQUENCE']._serialized_end=7282 + _globals['_QUANTITY']._serialized_start=7284 + _globals['_QUANTITY']._serialized_end=7408 + _globals['_MEASUREMENTREF']._serialized_start=7410 + _globals['_MEASUREMENTREF']._serialized_end=7493 + _globals['_UNITTERM']._serialized_start=7495 + _globals['_UNITTERM']._serialized_end=7579 + _globals['_UNITFACTOR']._serialized_start=7581 + _globals['_UNITFACTOR']._serialized_end=7628 + _globals['_DIAGNOSTIC']._serialized_start=7630 + _globals['_DIAGNOSTIC']._serialized_end=7704 + _globals['_SPAN']._serialized_start=7706 + _globals['_SPAN']._serialized_end=7800 + _globals['_SERVERINFOREQUEST']._serialized_start=7802 + _globals['_SERVERINFOREQUEST']._serialized_end=7821 + _globals['_SERVERINFORESPONSE']._serialized_start=7823 + _globals['_SERVERINFORESPONSE']._serialized_end=7882 + _globals['_QUERYREQUEST']._serialized_start=7884 + _globals['_QUERYREQUEST']._serialized_end=7967 + _globals['_QUERYRESPONSE']._serialized_start=7969 + _globals['_QUERYRESPONSE']._serialized_end=8029 + _globals['_QUERY']._serialized_start=8031 + _globals['_QUERY']._serialized_end=8103 + _globals['_CONSTRAINT']._serialized_start=8105 + _globals['_CONSTRAINT']._serialized_end=8229 + _globals['_PRIMITIVECONSTRAINT']._serialized_start=8231 + _globals['_PRIMITIVECONSTRAINT']._serialized_end=8346 + _globals['_COMPOSITECONSTRAINT']._serialized_start=8348 + _globals['_COMPOSITECONSTRAINT']._serialized_end=8452 + _globals['_QUERYRESULTELEMENT']._serialized_start=8455 + _globals['_QUERYRESULTELEMENT']._serialized_end=8615 + _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_start=8566 + _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_end=8615 + _globals['_SWEEPRANGE']._serialized_start=8617 + _globals['_SWEEPRANGE']._serialized_end=8732 + _globals['_RUNSWEEPREQUEST']._serialized_start=8735 + _globals['_RUNSWEEPREQUEST']._serialized_end=9055 _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_start=1782 _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_end=1849 - _globals['_SWEEPROW']._serialized_start=9038 - _globals['_SWEEPROW']._serialized_end=9238 - _globals['_RUNSWEEPRESPONSE']._serialized_start=9241 - _globals['_RUNSWEEPRESPONSE']._serialized_end=9478 - _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_start=9480 - _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_end=9590 - _globals['_DOCUMENTQUERYBINDING']._serialized_start=9592 - _globals['_DOCUMENTQUERYBINDING']._serialized_end=9671 - _globals['_DOCUMENTVALUE']._serialized_start=9674 - _globals['_DOCUMENTVALUE']._serialized_end=9887 - _globals['_DOCUMENTQUERYCOLUMN']._serialized_start=9889 - _globals['_DOCUMENTQUERYCOLUMN']._serialized_end=9924 - _globals['_DOCUMENTQUERYCELL']._serialized_start=9926 - _globals['_DOCUMENTQUERYCELL']._serialized_end=9983 - _globals['_DOCUMENTQUERYROW']._serialized_start=9985 - _globals['_DOCUMENTQUERYROW']._serialized_end=10083 - _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_start=10085 - _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_end=10195 - _globals['_RENDERDOCUMENTREQUEST']._serialized_start=10197 - _globals['_RENDERDOCUMENTREQUEST']._serialized_end=10261 - _globals['_RENDERDOCUMENTRESPONSE']._serialized_start=10263 - _globals['_RENDERDOCUMENTRESPONSE']._serialized_end=10305 - _globals['_SYSMLSERVICE']._serialized_start=11263 - _globals['_SYSMLSERVICE']._serialized_end=12707 + _globals['_SWEEPROW']._serialized_start=9058 + _globals['_SWEEPROW']._serialized_end=9258 + _globals['_RUNSWEEPRESPONSE']._serialized_start=9261 + _globals['_RUNSWEEPRESPONSE']._serialized_end=9498 + _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_start=9500 + _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_end=9610 + _globals['_DOCUMENTQUERYBINDING']._serialized_start=9612 + _globals['_DOCUMENTQUERYBINDING']._serialized_end=9691 + _globals['_DOCUMENTVALUE']._serialized_start=9694 + _globals['_DOCUMENTVALUE']._serialized_end=9907 + _globals['_DOCUMENTQUERYCOLUMN']._serialized_start=9909 + _globals['_DOCUMENTQUERYCOLUMN']._serialized_end=9944 + _globals['_DOCUMENTQUERYCELL']._serialized_start=9946 + _globals['_DOCUMENTQUERYCELL']._serialized_end=10003 + _globals['_DOCUMENTQUERYROW']._serialized_start=10005 + _globals['_DOCUMENTQUERYROW']._serialized_end=10103 + _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_start=10105 + _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_end=10215 + _globals['_RENDERDOCUMENTREQUEST']._serialized_start=10217 + _globals['_RENDERDOCUMENTREQUEST']._serialized_end=10281 + _globals['_RENDERDOCUMENTRESPONSE']._serialized_start=10283 + _globals['_RENDERDOCUMENTRESPONSE']._serialized_end=10325 + _globals['_SYSMLSERVICE']._serialized_start=11283 + _globals['_SYSMLSERVICE']._serialized_end=12727 # @@protoc_insertion_point(module_scope) diff --git a/clients/python/opensysml/proto/sysml_pb2.pyi b/clients/python/opensysml/proto/sysml_pb2.pyi index 9fb7855a5..c9b193c9c 100644 --- a/clients/python/opensysml/proto/sysml_pb2.pyi +++ b/clients/python/opensysml/proto/sysml_pb2.pyi @@ -686,7 +686,7 @@ class AttributeInfo(_message.Message): def __init__(self, name: _Optional[str] = ..., type: _Optional[str] = ..., value: _Optional[_Union[Value, _Mapping]] = ..., unit: _Optional[str] = ...) -> None: ... class Value(_message.Message): - __slots__ = ("int_value", "real_value", "bool_value", "string_value", "instance_id", "sequence", "null", "quantity", "enum_literal", "unset", "complex", "array", "vector", "vector_quantity", "measurement_ref") + __slots__ = ("int_value", "real_value", "bool_value", "string_value", "instance_id", "sequence", "null", "quantity", "enum_literal", "unset", "complex", "array", "vector", "vector_quantity", "measurement_ref", "infinity") INT_VALUE_FIELD_NUMBER: _ClassVar[int] REAL_VALUE_FIELD_NUMBER: _ClassVar[int] BOOL_VALUE_FIELD_NUMBER: _ClassVar[int] @@ -702,6 +702,7 @@ class Value(_message.Message): VECTOR_FIELD_NUMBER: _ClassVar[int] VECTOR_QUANTITY_FIELD_NUMBER: _ClassVar[int] MEASUREMENT_REF_FIELD_NUMBER: _ClassVar[int] + INFINITY_FIELD_NUMBER: _ClassVar[int] int_value: int real_value: float bool_value: bool @@ -717,7 +718,8 @@ class Value(_message.Message): vector: Vector vector_quantity: VectorQuantity measurement_ref: MeasurementRef - def __init__(self, int_value: _Optional[int] = ..., real_value: _Optional[float] = ..., bool_value: _Optional[bool] = ..., string_value: _Optional[str] = ..., instance_id: _Optional[int] = ..., sequence: _Optional[_Union[ValueSequence, _Mapping]] = ..., null: _Optional[str] = ..., quantity: _Optional[_Union[Quantity, _Mapping]] = ..., enum_literal: _Optional[_Union[EnumLiteral, _Mapping]] = ..., unset: _Optional[bool] = ..., complex: _Optional[_Union[Complex, _Mapping]] = ..., array: _Optional[_Union[Array, _Mapping]] = ..., vector: _Optional[_Union[Vector, _Mapping]] = ..., vector_quantity: _Optional[_Union[VectorQuantity, _Mapping]] = ..., measurement_ref: _Optional[_Union[MeasurementRef, _Mapping]] = ...) -> None: ... + infinity: bool + def __init__(self, int_value: _Optional[int] = ..., real_value: _Optional[float] = ..., bool_value: _Optional[bool] = ..., string_value: _Optional[str] = ..., instance_id: _Optional[int] = ..., sequence: _Optional[_Union[ValueSequence, _Mapping]] = ..., null: _Optional[str] = ..., quantity: _Optional[_Union[Quantity, _Mapping]] = ..., enum_literal: _Optional[_Union[EnumLiteral, _Mapping]] = ..., unset: _Optional[bool] = ..., complex: _Optional[_Union[Complex, _Mapping]] = ..., array: _Optional[_Union[Array, _Mapping]] = ..., vector: _Optional[_Union[Vector, _Mapping]] = ..., vector_quantity: _Optional[_Union[VectorQuantity, _Mapping]] = ..., measurement_ref: _Optional[_Union[MeasurementRef, _Mapping]] = ..., infinity: _Optional[bool] = ...) -> None: ... class Array(_message.Message): __slots__ = ("dimensions", "elements") diff --git a/clients/python/opensysml/values.py b/clients/python/opensysml/values.py index 35cbb7fb4..920e2ba46 100644 --- a/clients/python/opensysml/values.py +++ b/clients/python/opensysml/values.py @@ -668,6 +668,30 @@ def __repr__(self) -> str: UNSET = UnsetType() +class _Infinity: + """The unbounded value ``*``: no number, ordered above every finite one. + + A singleton, so ``is INFINITY`` tests it; also the unbounded multiplicity a + document query may answer with. + """ + + _instance = None + + def __new__(cls): + if cls._instance is None: + cls._instance = super().__new__(cls) + return cls._instance + + def __repr__(self) -> str: + return "INFINITY" + + __str__ = __repr__ + + +#: The unbounded value ``*``. See :class:`_Infinity`. +INFINITY = _Infinity() + + def value_to_python(pb_value, resolve_instance=None): """Convert a protobuf Value into a plain Python value. @@ -677,7 +701,8 @@ def value_to_python(pb_value, resolve_instance=None): when omitted, instance references are returned as their integer id. Returns: - int, float, complex, bool, str, list, None, :data:`UNSET`, a + int, float, complex, bool, str, list, None, :data:`UNSET`, + :data:`INFINITY`, a :class:`Quantity`, a :class:`MeasurementRef`, an :class:`Array`, a :class:`Vector`, a :class:`VectorQuantity`, an :class:`~opensysml.enumeration.EnumLiteral`, @@ -720,6 +745,12 @@ def value_to_python(pb_value, resolve_instance=None): return EnumLiteral(lit.literal_id, lit.enumeration_id, lit.name) if kind == 'unset': return UNSET + if kind == 'infinity': + # Only an asserted arm carries the unbounded value. + if not pb_value.infinity: + raise UnsupportedValueError( + "the infinity arm states no value unless it is true") + return INFINITY if kind == 'null': # A non-empty null carries the reason the value could not be sent. if pb_value.null: diff --git a/clients/python/tests/test_infinity.py b/clients/python/tests/test_infinity.py new file mode 100644 index 000000000..f9414ea2b --- /dev/null +++ b/clients/python/tests/test_infinity.py @@ -0,0 +1,31 @@ +"""Tests for the unbounded value ``*`` as a Python value. + +The infinity arm is a boolean, and only ``true`` asserts the value: a ``false`` +arm is malformed transport data rather than an unbounded number. +""" + +import pytest + +from opensysml.errors import UnsupportedValueError +from opensysml.proto import sysml_pb2 +from opensysml.values import INFINITY, value_to_python + + +def test_an_asserted_infinity_arm_is_the_unbounded_value(): + assert value_to_python(sysml_pb2.Value(infinity=True)) is INFINITY + + +def test_a_denied_infinity_arm_is_malformed(): + with pytest.raises(UnsupportedValueError): + value_to_python(sysml_pb2.Value(infinity=False)) + + +def test_a_denied_infinity_arm_nested_in_a_sequence_is_malformed(): + sequence = sysml_pb2.Value( + sequence=sysml_pb2.ValueSequence( + elements=[sysml_pb2.Value(int_value=1), sysml_pb2.Value(infinity=False)] + ) + ) + + with pytest.raises(UnsupportedValueError): + value_to_python(sequence) diff --git a/clients/rust/conformance/sysml.descriptor.binpb b/clients/rust/conformance/sysml.descriptor.binpb index c25df9379..4ff628720 100644 Binary files a/clients/rust/conformance/sysml.descriptor.binpb and b/clients/rust/conformance/sysml.descriptor.binpb differ diff --git a/clients/rust/opensysml/src/domain.rs b/clients/rust/opensysml/src/domain.rs index f79c0a389..231ad2635 100644 --- a/clients/rust/opensysml/src/domain.rs +++ b/clients/rust/opensysml/src/domain.rs @@ -414,6 +414,8 @@ pub enum Value { Null, /// A materialized feature with no value. Unset, + /// The unbounded value `*`, ordered above every finite magnitude. + Infinity, } pub(crate) fn value_from_wire(value: wire::Value) -> Result { @@ -474,6 +476,15 @@ pub(crate) fn value_from_wire(value: wire::Value) -> Result { name: v.name, })), wire::value::Kind::Unset(_) => Ok(Value::Unset), + // Only an asserted arm carries the unbounded value. + wire::value::Kind::Infinity(asserted) => { + if !asserted { + return Err(Error::Decode( + "the infinity arm states no value unless it is true".to_owned(), + )); + } + Ok(Value::Infinity) + } } } @@ -490,6 +501,7 @@ fn kind_name(kind: &wire::value::Kind) -> &'static str { wire::value::Kind::Quantity(_) => "quantity", wire::value::Kind::EnumLiteral(_) => "enum_literal", wire::value::Kind::Unset(_) => "unset", + wire::value::Kind::Infinity(_) => "infinity", wire::value::Kind::Complex(_) => "complex", wire::value::Kind::Array(_) => "array", wire::value::Kind::Vector(_) => "vector", @@ -914,6 +926,21 @@ mod tests { ); } + #[test] + fn only_an_asserted_infinity_arm_is_the_unbounded_value() { + let arm = |asserted| wire::Value { + kind: Some(wire::value::Kind::Infinity(asserted)), + }; + assert_eq!(value_from_wire(arm(true)).ok(), Some(Value::Infinity)); + assert!(matches!(value_from_wire(arm(false)), Err(Error::Decode(_)))); + let nested = wire::Value { + kind: Some(wire::value::Kind::Sequence(wire::ValueSequence { + elements: vec![arm(false)], + })), + }; + assert!(matches!(value_from_wire(nested), Err(Error::Decode(_)))); + } + #[test] fn a_complex_number_prints_in_rectangular_form() { let print = |real, imaginary| Complex { real, imaginary }.to_string(); diff --git a/clients/rust/opensysml/src/proto/sysml/sysml.rs b/clients/rust/opensysml/src/proto/sysml/sysml.rs index bfb869cb4..a809e0542 100644 --- a/clients/rust/opensysml/src/proto/sysml/sysml.rs +++ b/clients/rust/opensysml/src/proto/sysml/sysml.rs @@ -825,7 +825,7 @@ pub struct AttributeInfo { /// Value represents a runtime-evaluable value #[derive(Clone, PartialEq, ::prost::Message)] pub struct Value { - #[prost(oneof="value::Kind", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15")] + #[prost(oneof="value::Kind", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16")] pub kind: ::core::option::Option, } /// Nested message and enum types in `Value`. @@ -872,6 +872,11 @@ pub mod value { /// a unit by itself, no magnitude #[prost(message, tag="15")] MeasurementRef(super::MeasurementRef), + /// The unbounded value `*`, which is no number and no string: ordered above + /// every finite magnitude and refused by arithmetic. Always true when set, + /// as DocumentValue.infinity is. + #[prost(bool, tag="16")] + Infinity(bool), } } /// Array is a Collections::Array: its elements flattened in row-major order diff --git a/docs/project/spec-compliance.md b/docs/project/spec-compliance.md index 7eebecded..2307c6088 100644 --- a/docs/project/spec-compliance.md +++ b/docs/project/spec-compliance.md @@ -659,6 +659,8 @@ by name is refused naming what is missing rather than approximated. | Unary operators (-, +, not) | `eval.go` evalUnary | `calc_unary_operators.sysml` | ✅ Faithful | | Conditional (`if c ? a else b`) and null coalescing (`??`), both lazy | `eval.go` evalConditional/evalNullCoalesce | `calc_conditional_branch.sysml`, `calc_null_coalesce.sysml` | ✅ Faithful | | Literal values (Integer, Real, Boolean, String) | `eval.go:109` evalLiteral* | `calc_simple_add.sysml` | ✅ Faithful | +| `*` in an expression position is the unbounded value (KerML §8.4.4.6 `LiteralInfinity`, typed `ScalarValues::Positive`): it exceeds every finite Integer, Real and Natural, equals itself, orders consistently under `<`, `<=`, `>`, `>=`, and prints as `*` in a value, a trace, a solver pin and a document-query cell. It is no number, so every arithmetic operation over it — `+`, `-`, `*`, `/`, `%`, `**`, unary `+` and unary `-` — is `ErrTypeMismatch` naming the operation, never an infinity, a NaN or a finite answer | `runtime/eval.go` `evalLiteralInfinity`, `constArithmetic`, `constCompare`; `semantics/eval.go` `Value.IsUnbounded`, `UnboundedOrder`, `OrderSatisfies`, `FormatConst`; `semantics/valuetype.go` `exprConformance`; `solve/pin.go`; `repl/docquery.go` | `runtime/infinity_test.go:TestInfinityValue`, `:TestInfinityComparison`, `:TestInfinityArithmeticRefused`; conformance `value_unbounded_comparison`, `value_unbounded_arithmetic_refused`; `parse/unbounded_and_metadata_access.golden`; `robustness_test.go:arithmetic_over_the_unbounded_value`, `:unbounded_value_compared_with_a_string` | ✅ Faithful | +| `ref.metadata` is a MetadataAccessExpression (KerML §8.4.4.10): it yields the metadata annotating the element `ref` names as a sequence of metadata instances in declaration order — inline `@`-annotations first, `metadata … about` ones after — each instance carrying the feature values the annotation body binds and, where the body binds none, the metadata type's own declared defaults. An element no metadata annotates yields the empty sequence; metadata read off a value (`1.metadata`) is `ErrTypeMismatch`, and a name that resolves to nothing is `ErrUnresolvedReference` | `parser/expr.go` `parsePostfixes` (`metadataAccessRef`); `semantics/annotations.go` `Model.ElementMetadataOf`, `metadataBindings` (the annotation side table an element filter classifies by); `runtime/metadata.go` `evalMetadataAccess`, `metadataSubject`, `metadataInstance`; `semantics/annotations.go` `aboutAnnotations` reaches an `about` annotation from a re-indexed twin of the annotated symbol, so the prompt's own scope tree reads it as the index does | `runtime/metadata_test.go:TestMetadataAccessBoundValues`, `:TestMetadataAccessAboutForm`, `:TestMetadataAccessEmpty`, `:TestMetadataAccessNotAnElement`, `:TestMetadataAccessUnresolved`, `:TestMetadataAccessUnknownFeature`; conformance `metadata_access_annotations`; `parse/unbounded_and_metadata_access.golden`; `robustness_test.go:metadata_of_a_value`, `:metadata_of_an_unresolved_name`; `repl/metadata_about_eval_test.go:TestEvalMetadataReadsAboutAnnotations` | ✅ Faithful | | Feature reference resolution | `eval.go:141` evalFeatureReference | `constraint_literal.sysml` | ✅ Faithful | | Qualified name resolution (A::B::C) | `eval.go:53` Eval + `resolve/qualified.go` | `calc_qualified_names.sysml` | ✅ Faithful | | A qualified name evaluates as the checker resolves it, imports included (KerML §8.2.3.5 import, §8.2.3.3 visibility): a segment that names a member a `public import` re-exports — of every member (`Bq::x` with `public import A::*`), of one (`public import A::x`), recursively (`import A::**`), through a façade of a façade, by short name or through an `alias` — reaches the same element the checker reaches, which is how the library's `ISQ` and `SI` re-export the ISQ part packages (`ISQ::speed`, `SI::speed`); a `private import` stays reachable only from inside the importing namespace, and a name the checker rejects fails at evaluation with the checker's own message and classification (`unresolved reference: Priv::x`; `ambiguous reference: Twice::t (2 candidates)` when several members answer to a segment) | `runtime/eval.go` `evalNameGeneral` resolves the whole name through `resolve.Resolver.ReadQualified` (the checker's `walkQualified`, so the two tiers cannot disagree), whose `Reading` carries the element, the resolved segments — routing a calc usage's outputs to `evalCalcUsageMembers` and keeping the variant/literal reports in `unresolvedQualifiedName` — and the candidate count of a name rejected as ambiguous; a reading is memoized by scope and node, so one expression evaluated in several scopes answers in each with what that scope sees | `calc_qualified_name_through_import.sysml`, `calc_qualified_name_private_import.sysml`, `calc_qualified_name_ambiguous.sysml`, `qualified_import_test.go:TestQualifiedNameThroughImportEvaluates`, `:TestQualifiedNameThroughImportRejectedAsChecked`, `:TestQualifiedNameThroughImportKeepsTypedErrors`, `:TestLibraryQuantityThroughFacadeResolves`, `:TestQualifiedNameEvaluatedInSeveralScopes`, `resolve/reading_test.go:TestReadQualifiedAnswersPerScope`, `:TestReadQualifiedReportsFailure` | ✅ Faithful (a library quantity reached through a façade resolves to its declaration, which like `SI::m` carries no scalar value, so the evaluator reports that declaration rather than a missing member) | diff --git a/docs/reference/service-transports.md b/docs/reference/service-transports.md index 5200052a1..0a2b070c4 100644 --- a/docs/reference/service-transports.md +++ b/docs/reference/service-transports.md @@ -52,10 +52,11 @@ capability's definition rather than something a client has to guess: | The capability describes | A request that needs it | What a client should do | |---|---|---| | what the service can be *asked*: `strict_conformance`, `inline_language`, `parse_sources`, `evaluate_subject`, `verification`, `convert`, `apply_edits`, `authoring`, `query`, `oslc_query`, `document_query`, `render_document` | is **refused** with `UNIMPLEMENTED`, naming the capability | check the advertised list first, and report the missing capability locally rather than spending a round trip | -| how a response is *populated*: `type_facts`, `symbol_attributes`, `feature_values`, `enum_values`, `unset_value`, `complex_values`, `structured_values`, `measurement_refs`, `verification_verdicts` | is answered with those fields **omitted** | check before reading the fields; an omitted field is not an error | +| how a response is *populated*: `type_facts`, `symbol_attributes`, `feature_values`, `enum_values`, `unset_value`, `complex_values`, `structured_values`, `measurement_refs`, `verification_verdicts`, `infinity_value` | is answered with those fields **omitted** | check before reading the fields; an omitted field is not an error | -`complex_values`, `structured_values` and `measurement_refs` sit in both rows: a complex — or -an array, vector or vector quantity, or a bare measurement reference — in a response is +`complex_values`, `structured_values`, `measurement_refs` and `infinity_value` sit in both +rows: a complex — or an array, vector or vector quantity, a bare measurement reference, or the +unbounded value `*` — in a response is reported as an `unsupported` null without it, and one in an action input or calc argument is refused with `UNIMPLEMENTED` rather than read as another value — a service that predates the arm would read it as an unknown field, so every client checks the list before sending one diff --git a/docs/reference/wire-contract.md b/docs/reference/wire-contract.md index 96d298204..94340faf3 100644 --- a/docs/reference/wire-contract.md +++ b/docs/reference/wire-contract.md @@ -217,6 +217,7 @@ arms, each captured from `Evaluate` against the model at the end of this section | `vector` | object | `{"result":{"vector":{"components":[{"realValue":3},{"realValue":4}]}}}` | Numeric vector; each component an `intValue` or `realValue` | | `vectorQuantity` | object | `{"result":{"vectorQuantity":{"components":[{"realMagnitude":3,"unit":"m","unitTerm":{…}},…]}}}` | Vector of quantities; one `quantity` body per component | | `measurementRef` | object | `{"result":{"measurementRef":{"unit":"m","unitTerm":{…},"unitId":"SI::metre"}}}` | A measurement reference on its own: a unit, its reduction, and the declaration it names | +| `infinity` | boolean | `{"result":{"infinity":true}}` | The unbounded value `*`, which is no number and no string | The `array`, `vector` and `vectorQuantity` rows were captured against `conformance/fixtures/structured.sysml` (`S::grid`, `S::v`, `S::d`), `measurementRef` against @@ -281,6 +282,11 @@ decode(v): measurementRef → unit := v.measurementRef.unit, id := v.measurementRef.unitId; require v.measurementRef.unitTerm when either is present, else an error; require unit or id, else an error; id absent means a composed unit + infinity → the language's unbounded sentinel, distinct from a number and from the + string "*"; it compares above every finite number and equals itself. + The arm is the value itself, so only true carries it: a caller sending + infinity: false, directly or nested, is answered with an error rather + than with the unbounded value anything else → an error: a newer service than this decoder ``` diff --git a/internal/core/parser/expr.go b/internal/core/parser/expr.go index 33e7d8ddd..2df55874e 100644 --- a/internal/core/parser/expr.go +++ b/internal/core/parser/expr.go @@ -200,6 +200,19 @@ func (p *Parser) parsePrimary() ast.Node { return p.parsePostfixes(start, expr) } +// metadataAccessRef is the element reference `ref.metadata` reads the metadata +// of; nothing but a name is one (KerMLExpressions MetadataAccessExpression). +func metadataAccessRef(expr ast.Node) *ast.QualifiedName { + switch e := expr.(type) { + case *ast.FeatureReference: + return e.Name + case *ast.QualifiedName: + return e + default: + return nil + } +} + // atExprStart reports whether the current token can start an expression. func (p *Parser) atExprStart() bool { t := p.peek() @@ -242,6 +255,17 @@ func (p *Parser) parsePostfixes(start int, expr ast.Node) ast.Node { expr = c continue } + // `ref.metadata` is a MetadataAccessExpression over an element + // reference, not a chain through a feature named `metadata`. + if p.atKeyword("metadata") { + if ref := metadataAccessRef(expr); ref != nil { + p.advance() // metadata + m := &ast.MetadataAccessExpr{Ref: ref} + m.NodeSpan = p.spanFrom(start) + expr = m + continue + } + } // Use relaxed parsing to allow keywords as feature names (e.g., oSP.exit, state.entry) member := p.parseQualifiedNameRelaxed() fc := &ast.FeatureChainExpr{Operand: expr, Member: member} diff --git a/internal/core/parser/testdata/parse/unbounded_and_metadata_access.golden b/internal/core/parser/testdata/parse/unbounded_and_metadata_access.golden new file mode 100644 index 000000000..fd806ac3d --- /dev/null +++ b/internal/core/parser/testdata/parse/unbounded_and_metadata_access.golden @@ -0,0 +1,40 @@ +(RootNamespace + (Membership visibility="default" + (Package name="test" library=false standard=false + (Membership visibility="default" + (Definition kind="metadata" abstract=false variation=false name="Safety" + (Membership visibility="default" + (Usage kind="attribute" name="level" ref=false direction="none" composite=false derived=false ordered=false nonunique=false)))) + (Membership visibility="default" + (Definition kind="part" abstract=false variation=false name="Vehicle")) + (Membership visibility="default" + (Usage kind="part" name="seatBelt" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (Relationship kind="typing" target=Vehicle + (*ast.QualifiedName)) + (Membership visibility="default" + (PrefixMetadata type="Safety" + (Membership visibility="default" + (Usage kind="attribute" name="level" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (LiteralInteger value="4"))))))) + (Membership visibility="default" + (Definition kind="part" abstract=false variation=false name="Report" + (Membership visibility="default" + (Usage kind="attribute" name="unbounded" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (LiteralInfinity))) + (Membership visibility="default" + (Usage kind="attribute" name="exceedsFinite" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (OperatorExpr operator=">" + (LiteralInfinity) + (LiteralInteger value="1000")))) + (Membership visibility="default" + (Usage kind="attribute" name="annotations" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (MetadataAccessExpr ref="seatBelt"))) + (Membership visibility="default" + (Usage kind="attribute" name="qualified" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (MetadataAccessExpr ref="test::seatBelt"))) + (Membership visibility="default" + (Usage kind="attribute" name="level" ref=false direction="none" composite=false derived=false ordered=false nonunique=false + (FeatureChainExpr member="level" + (IndexExpr + (MetadataAccessExpr ref="seatBelt") + (LiteralInteger value="1")))))))))) \ No newline at end of file diff --git a/internal/core/parser/testdata/parse/unbounded_and_metadata_access.sysml b/internal/core/parser/testdata/parse/unbounded_and_metadata_access.sysml new file mode 100644 index 000000000..9a968b8c9 --- /dev/null +++ b/internal/core/parser/testdata/parse/unbounded_and_metadata_access.sysml @@ -0,0 +1,21 @@ +package test { + metadata def Safety { + attribute level; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + level = 4; + } + } + + part def Report { + attribute unbounded = *; + attribute exceedsFinite = * > 1000; + attribute annotations = seatBelt.metadata; + attribute qualified = test::seatBelt.metadata; + attribute level = seatBelt.metadata#(1).level; + } +} diff --git a/internal/core/runtime/adopt.go b/internal/core/runtime/adopt.go index d38e208c8..a2625642c 100644 --- a/internal/core/runtime/adopt.go +++ b/internal/core/runtime/adopt.go @@ -389,6 +389,12 @@ func (ctx *Context) declText(owner *symbols.Symbol, span source.Span) string { if owner != nil { file = owner.DocName } + return ctx.textIn(file, span) +} + +// textIn renders the text the named document wrote at the given span, falling +// back to the span for a document whose text this context was not given. +func (ctx *Context) textIn(file string, span source.Span) string { if sf, ok := ctx.sources[file]; ok && span.End() <= sf.Len() { return strings.Join(strings.Fields(sf.Text(span)), " ") } @@ -953,9 +959,10 @@ func (a *adoption) abandon() { } // carryDerived takes over the state the previous context derived about the -// objects carried over: which usage denotes which occurrence, and which variant -// each of them selected. What a rebound declaration no longer has is dropped, so -// it is derived again rather than kept wrong. +// objects carried over: which usage denotes which occurrence, which annotation +// denotes which object, and which variant each of them selected. What a rebound +// declaration no longer has is dropped, so it is derived again rather than kept +// wrong. func (a *adoption) carryDerived(adopted map[int64]bool) { for sym, id := range a.prev.occurrences { if !adopted[id] { @@ -969,6 +976,22 @@ func (a *adoption) carryDerived(adopted map[int64]bool) { a.ctx.occurrences[found] = id } } + for key, id := range a.prev.metadataObjects { + if !adopted[id] { + continue + } + element, err := a.rebind(key.element, "the element it annotates") + if err != nil { + continue + } + // An annotation denotes the object made for it only while it still reads + // as it read: an edited or reordered one is read again rather than reused. + stated := a.prev.metadataAnnotationDigest(key.element, key.index) + if stated == "" || stated != a.ctx.metadataAnnotationDigest(element, key.index) { + continue + } + a.ctx.metadataObjects[metadataAnnotation{element: element, index: key.index}] = id + } for key, id := range a.prev.variantObjects { if !adopted[key.owner] || !adopted[id] { continue diff --git a/internal/core/runtime/array.go b/internal/core/runtime/array.go index 184706614..2a1fe2a4f 100644 --- a/internal/core/runtime/array.go +++ b/internal/core/runtime/array.go @@ -241,6 +241,7 @@ const ( cartesianThreeVectorTypeFQN = "VectorValues::CartesianThreeVectorValue" vectorQuantityTypeFQN = "Quantities::VectorQuantityValue" scalarValueTypeFQN = "ScalarValues::ScalarValue" + positiveTypeFQN = "ScalarValues::Positive" ) // structuredFeature reads a library feature of an array, vector, vector, tensor diff --git a/internal/core/runtime/classifier_behavior.go b/internal/core/runtime/classifier_behavior.go index 69f9f7a7d..c38f467c0 100644 --- a/internal/core/runtime/classifier_behavior.go +++ b/internal/core/runtime/classifier_behavior.go @@ -302,6 +302,11 @@ func (ctx *Context) abandonInstancesBetween(mark, end int) { delete(ctx.occurrences, sym) } } + for annotation, id := range ctx.metadataObjects { + if _, live := ctx.instances[id]; !live { + delete(ctx.metadataObjects, annotation) + } + } ctx.forgetLives(abandoned) ctx.forgetVariantsNaming(abandoned) ctx.forgetEdgesOf(gone) diff --git a/internal/core/runtime/conformance_test.go b/internal/core/runtime/conformance_test.go index 85b0b9890..3ba2aebc8 100644 --- a/internal/core/runtime/conformance_test.go +++ b/internal/core/runtime/conformance_test.go @@ -1554,6 +1554,8 @@ func expectedToRuntimeValue(t *testing.T, ev ExpectedValue) Value { t.Fatalf("invalid String value type: %T", ev.Value) case "Null": return Value{Kind: ValNull} + case "Infinity": + return Value{Kind: ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}} case "Variant": t.Fatalf("a variant is named by the model, so it cannot be built from a case value") case "EnumLiteral": @@ -1687,6 +1689,10 @@ func validateValue(t reporter, ctx *Context, name string, expected ExpectedValue if actual.Kind != ValNull { t.Errorf("%s: type = %v, want Null", name, actual.Kind) } + case "Infinity": + if actual.Kind != ValConst || !actual.Const.IsUnbounded() { + t.Errorf("%s: type = %v (Const.Kind=%v), want the unbounded `*`", name, actual.Kind, actual.Const.Kind) + } case "Variant": if actual.Kind != ValVariant || actual.Variant() == nil { t.Errorf("%s: type = %v, want Variant", name, actual.Kind) diff --git a/internal/core/runtime/context.go b/internal/core/runtime/context.go index 6051e6f63..e3b3a201b 100644 --- a/internal/core/runtime/context.go +++ b/internal/core/runtime/context.go @@ -108,6 +108,11 @@ type Context struct { // occurrences holds the object each usage carrying no value of its own // denotes, so a feature chain through a part reads one occurrence of it. occurrences map[*symbols.Symbol]int64 + // metadataObjects holds the object each metadata annotation denotes, so + // reading `.metadata` twice reads one object per annotation. The annotation + // is named by the element it annotates and its place among that element's + // annotations, so a reanalysis can rebind it. + metadataObjects map[metadataAnnotation]int64 // behaving memoizes runsBehaviors per type; the model is fixed for the context's life. behaving map[*symbols.Symbol]bool // behavingFeatures memoizes behavingParts and redefGroups redefinitionGroups, per type. @@ -321,6 +326,7 @@ func NewContext(model *semantics.Model, resolver *resolve.Resolver, maxSteps int maxSweepRuns: DefaultMaxSweepRuns, occurrences: make(map[*symbols.Symbol]int64), + metadataObjects: make(map[metadataAnnotation]int64), behaving: make(map[*symbols.Symbol]bool), behavingFeatures: make(map[*symbols.Symbol][]int), redefGroups: make(map[*symbols.Symbol][][]string), diff --git a/internal/core/runtime/eval.go b/internal/core/runtime/eval.go index c2911178d..5df75b906 100644 --- a/internal/core/runtime/eval.go +++ b/internal/core/runtime/eval.go @@ -274,6 +274,10 @@ func (ec *EvalContext) eval(node ast.Node) (Value, error) { return ec.evalLiteralBool(n) case *ast.LiteralString: return ec.evalLiteralString(n) + case *ast.LiteralInfinity: + return ec.evalLiteralInfinity(n) + case *ast.MetadataAccessExpr: + return ec.evalMetadataAccess(n) case *ast.NullExpr: return ec.evalNull(n) case *ast.FeatureReference: @@ -397,6 +401,12 @@ func (ec *EvalContext) evalLiteralString(n *ast.LiteralString) (Value, error) { } // evalNull evaluates a null expression. +// evalLiteralInfinity evaluates `*`, the unbounded value: a scalar constant of +// its own, ordered above every finite number and refused by arithmetic. +func (ec *EvalContext) evalLiteralInfinity(_ *ast.LiteralInfinity) (Value, error) { + return Value{Kind: ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}}, nil +} + func (ec *EvalContext) evalNull(n *ast.NullExpr) (Value, error) { return Value{Kind: ValNull}, nil } @@ -1112,12 +1122,18 @@ func (ec *EvalContext) chainMemberValue(value Value, parts []ast.NameSegment, fr } return ec.chainMemberValue(Value{Kind: ValInstance, Instance: inst.ID}, parts, from) default: + if err := metadataOfAValue(value, parts); err != nil { + return Value{}, err + } return Value{}, fmt.Errorf("cannot chain through non-instance member %s (%v)", from, value.Kind) } // A selected variant is chained through the object it materialized. id, isObject := value.Object() if !isObject { + if err := metadataOfAValue(value, parts); err != nil { + return Value{}, err + } return Value{}, fmt.Errorf("cannot chain through non-instance member %s (%v)", from, value.Kind) } inst, ok := ec.ctx.instances[id] @@ -1461,6 +1477,12 @@ func (ctx *Context) directValueType(scope *symbols.Scope, value Value) (*symbols name = "Real" case semantics.ValBool: name = "Boolean" + case semantics.ValInfinity: + // `*` is the natural number exceeding every other (KerML 8.4.4.6). + if positive := ctx.librarySymbol(positiveTypeFQN); positive != nil { + return positive, nil + } + return nil, fmt.Errorf("%w: direct type %q", ErrUndeterminedValueType, positiveTypeFQN) default: return nil, fmt.Errorf("%w: %s", ErrUndeterminedValueType, value.Kind) } @@ -1783,6 +1805,13 @@ func arithmeticValues(op ast.OperatorKind, left, right Value, span source.Span) // evaluator and the compiled calc tier share so both report the same results // and the same errors. func constArithmetic(op ast.OperatorKind, left, right semantics.Value) (semantics.Value, error) { + // The unbounded `*` is no number: arithmetic over it is refused rather than + // answered with a finite result or an infinity. + if left.IsUnbounded() || right.IsUnbounded() { + return semantics.Value{}, fmt.Errorf("%w: operator '%s' is not defined for the unbounded value '*': %s %s %s", + ErrTypeMismatch, op, semantics.FormatConst(left), op, semantics.FormatConst(right)) + } + // Exponentiation shares the folder's implementation, so a folded and an // evaluated `**` agree; the folder declines where this reports the error. if op == ast.OpPow { @@ -1957,6 +1986,20 @@ func comparisonValues(op ast.OperatorKind, left, right Value, span source.Span) // constComparison orders two scalar constants, the core the evaluator and the // compiled calc tier share. func constComparison(op ast.OperatorKind, left, right semantics.Value) (bool, error) { + // The unbounded `*` orders above every finite number and equals itself. + if left.IsUnbounded() || right.IsUnbounded() { + order, ok := semantics.UnboundedOrder(left, right) + if !ok { + return false, fmt.Errorf("%w: '%s' is not defined between %s and %s", + ErrTypeMismatch, op, semantics.FormatConst(left), semantics.FormatConst(right)) + } + res, ok := semantics.OrderSatisfies(op, order) + if !ok { + return false, fmt.Errorf("unknown comparison operator: %v", op) + } + return res, nil + } + // Compare integers if left.Kind == semantics.ValInt && right.Kind == semantics.ValInt { switch op { diff --git a/internal/core/runtime/infinity_test.go b/internal/core/runtime/infinity_test.go new file mode 100644 index 000000000..3e8e0a5d8 --- /dev/null +++ b/internal/core/runtime/infinity_test.go @@ -0,0 +1,158 @@ +package runtime + +import ( + "errors" + "strings" + "testing" + + "github.com/Open-MBEE/OpenSysML/internal/core/ast" + "github.com/Open-MBEE/OpenSysML/internal/core/semantics" + "github.com/Open-MBEE/OpenSysML/internal/core/symbols" +) + +// evalDeclaredExpr evaluates expr as the value of an attribute declared beside src. +func evalDeclaredExpr(t *testing.T, src, expr string) (*Context, Value, error) { + t.Helper() + ctx, scope, decl := declaredExpr(t, src, expr) + got, err := NewEvalContext(ctx, scope).Eval(decl) + return ctx, got, err +} + +// declaredExpr is expr as the value of an attribute declared beside src, with +// the context and scope to evaluate it in, so one context can evaluate it twice. +func declaredExpr(t *testing.T, src, expr string) (*Context, *symbols.Scope, ast.Node) { + t.Helper() + full := src + "\npackage probe {\n\tattribute result = " + expr + ";\n}" + model, resolver, root := parseAndBuildLibraryModel(t, full) + pkg, ok := root.LookupLocal("probe") + if !ok || pkg == nil || pkg.Scope == nil { + t.Fatal("package probe has no scope") + } + sym, ok := pkg.Scope.LookupLocal("result") + if !ok || sym == nil { + t.Fatal("attribute result not found") + } + decl, ok := sym.Decl.(*ast.Usage) + if !ok { + t.Fatalf("result declares %T, want a usage", sym.Decl) + } + return NewContext(model, resolver, 10000), pkg.Scope, decl.Value +} + +// TestInfinityValue evaluates `*`: its own scalar value, printed as written. +func TestInfinityValue(t *testing.T) { + _, got, err := evalDeclaredExpr(t, "package test {}", "*") + if err != nil { + t.Fatalf("* failed: %v", err) + } + if got.Kind != ValConst || !got.Const.IsUnbounded() { + t.Fatalf("* evaluated to %v (%v), want the unbounded constant", got.Kind, got.Const.Kind) + } + if text := FormatValue(got); text != "*" { + t.Errorf("FormatValue = %q, want %q", text, "*") + } + if text := FormatTraceValue(got); text != "*" { + t.Errorf("FormatTraceValue = %q, want %q", text, "*") + } +} + +// TestInfinityComparison orders `*` above every finite number and equal to itself. +func TestInfinityComparison(t *testing.T) { + cases := []struct { + expr string + want bool + }{ + {"* > 1", true}, + {"* > 1.5", true}, + {"* > -100", true}, + {"1 < *", true}, + {"* >= 7", true}, + {"* <= 1", false}, + {"* < 1", false}, + {"* == *", true}, + {"* >= *", true}, + {"* <= *", true}, + {"* > *", false}, + {"* < *", false}, + {"* != *", false}, + {"* == 1", false}, + {"* != 1", true}, + } + for _, tc := range cases { + t.Run(tc.expr, func(t *testing.T) { + _, got, err := evalDeclaredExpr(t, "package test {}", tc.expr) + if err != nil { + t.Fatalf("%s failed: %v", tc.expr, err) + } + if got.Kind != ValConst || got.Const.Kind != semantics.ValBool { + t.Fatalf("%s evaluated to %v, want a Boolean", tc.expr, got.Kind) + } + if got.Const.Bool != tc.want { + t.Errorf("%s = %v, want %v", tc.expr, got.Const.Bool, tc.want) + } + }) + } +} + +// TestInfinityArithmeticRefused refuses arithmetic over `*` with a typed error +// naming the operation rather than answering with a number. +func TestInfinityArithmeticRefused(t *testing.T) { + cases := []struct { + expr string + want string + }{ + {"* + 1", "operator '+' is not defined for the unbounded value '*'"}, + {"1 + *", "operator '+' is not defined for the unbounded value '*'"}, + {"* - 1", "operator '-' is not defined for the unbounded value '*'"}, + {"2 * *", "operator '*' is not defined for the unbounded value '*'"}, + {"* / 2", "operator '/' is not defined for the unbounded value '*'"}, + {"* % 2", "operator '%' is not defined for the unbounded value '*'"}, + {"* ** 2", "operator '**' is not defined for the unbounded value '*'"}, + {"-*", "unary '-' is not defined for *"}, + {"+*", "unary '+' is not defined for *"}, + {`* > "a"`, "'>' is not defined"}, + } + for _, tc := range cases { + t.Run(tc.expr, func(t *testing.T) { + _, _, err := evalDeclaredExpr(t, "package test {}", tc.expr) + if err == nil { + t.Fatalf("%s succeeded, want a typed error", tc.expr) + } + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("%s: error %v, want a type mismatch", tc.expr, err) + } + if !strings.Contains(err.Error(), tc.want) { + t.Errorf("%s: error %q, want it to contain %q", tc.expr, err, tc.want) + } + if strings.Contains(err.Error(), "∞") || strings.Contains(err.Error(), "Inf") { + t.Errorf("%s: error %q names the value as an infinity, want `*`", tc.expr, err) + } + }) + } +} + +// TestInfinityDirectType classifies `*` as the Positive it is typed as in +// expression position, and so as a Natural, but as nothing unrelated. +func TestInfinityDirectType(t *testing.T) { + cases := map[string]string{ + "* istype ScalarValues::Positive": "true", + "* hastype ScalarValues::Positive": "true", + "* istype ScalarValues::Natural": "true", + // hastype demands the direct type itself, which Natural is only above. + "* hastype ScalarValues::Natural": "false", + "* istype ScalarValues::String": "false", + "* hastype ScalarValues::Boolean": "false", + "* @ ScalarValues::Positive": "true", + "* @ ScalarValues::String": "false", + } + for expr, want := range cases { + _, got, err := evalDeclaredExpr(t, "package test {}", expr) + if err != nil { + t.Errorf("%s failed: %v", expr, err) + continue + } + if text := FormatValue(got); text != want { + t.Errorf("%s = %s, want %s", expr, text, want) + } + } +} diff --git a/internal/core/runtime/invoke_calc_body_test.go b/internal/core/runtime/invoke_calc_body_test.go index a63fee787..6b92f2d36 100644 --- a/internal/core/runtime/invoke_calc_body_test.go +++ b/internal/core/runtime/invoke_calc_body_test.go @@ -341,13 +341,13 @@ func TestCalcBodySuccessionIsNotAStep(t *testing.T) { const unevaluableResultModel = ` package test { item def Foo { attribute v; } - calc def mk { + calc def complement { in n; - Foo.metadata + ~n } - calc def unbounded { + calc def cast { in n; - * + n as Foo } } ` @@ -474,7 +474,7 @@ func TestUnevaluableResultIsNotReportedAsMissing(t *testing.T) { idx, _, ctx := buildRuntime(t, "", parseAndBuild(t, unevaluableResultModel)) root := idx.DocumentRoot("") - for _, name := range []string{"mk", "unbounded"} { + for _, name := range []string{"complement", "cast"} { calc, scope := calcByName(t, root, "test", name) _, err := ctx.InvokeCalc(calc, []Value{constInt(1)}, scope) if err == nil { diff --git a/internal/core/runtime/metadata.go b/internal/core/runtime/metadata.go new file mode 100644 index 000000000..5fab69fe5 --- /dev/null +++ b/internal/core/runtime/metadata.go @@ -0,0 +1,187 @@ +package runtime + +import ( + "fmt" + + "github.com/Open-MBEE/OpenSysML/internal/core/ast" + "github.com/Open-MBEE/OpenSysML/internal/core/semantics" + "github.com/Open-MBEE/OpenSysML/internal/core/symbols" +) + +// evalMetadataAccess evaluates `ref.metadata` (KerML 8.4.4.10 MetadataAccessExpression): +// the metadata annotating the element ref names, as a sequence of objects of the +// annotating metadata types, in the order the annotations are stated. An element +// no metadata annotates reads as the empty sequence. +func (ec *EvalContext) evalMetadataAccess(n *ast.MetadataAccessExpr) (Value, error) { + sym, err := ec.metadataSubject(n) + if err != nil { + return Value{}, err + } + if ec.ctx.model == nil { + return Value{}, fmt.Errorf("%w: no model holds the metadata of %s", + ErrTypeMismatch, ec.ctx.qualifiedSymbolName(sym)) + } + annotations := ec.ctx.model.ElementMetadataOf(sym) + // One access answers every annotation or none: what a failing one wrote, made + // or started, here or in a behavior it woke, is undone with it. + commit, rollback := ec.ctx.beginJournal() + values := make([]Value, 0, len(annotations)) + for i, annotation := range annotations { + val, err := ec.metadataInstance(metadataAnnotation{element: sym, index: i}, annotation) + if err != nil { + rollback() + return Value{}, err + } + values = append(values, val) + } + seq, err := ec.newSequence(values) + if err != nil { + rollback() + return Value{}, err + } + commit() + return seq, nil +} + +// metadataSubject is the element `ref.metadata` reads the metadata of. A name +// that resolves to no element, or to something that is a value rather than an +// element, is refused rather than answered with an empty sequence. +func (ec *EvalContext) metadataSubject(n *ast.MetadataAccessExpr) (*symbols.Symbol, error) { + name := ast.QualifiedText(n.Ref) + if name == "" { + return nil, fmt.Errorf("%w: metadata access names no element", ErrTypeMismatch) + } + if ec.ctx == nil || ec.ctx.resolver == nil { + return nil, fmt.Errorf("%w: %s", ErrUnresolvedReference, name) + } + sym, ok := ec.ctx.resolver.ResolveQualified(ec.scope, n.Ref) + if !ok || sym == nil { + return nil, fmt.Errorf("%w: %s", ErrUnresolvedReference, name) + } + if resolved, aliasOK := ec.ctx.resolver.ResolveAliasTarget(sym); aliasOK { + sym = resolved + } + if sym.Decl == nil { + return nil, fmt.Errorf("%w: metadata access requires an element, but %s declares none", + ErrTypeMismatch, name) + } + return sym, nil +} + +// metadataOfAValue reports `.metadata` read from a value rather than an element: +// only an element is annotated, so a scalar has no metadata to answer with. +func metadataOfAValue(value Value, parts []ast.NameSegment) error { + if len(parts) == 0 || parts[0].Text != "metadata" { + return nil + } + return fmt.Errorf("%w: metadata access requires an element, but %s is a value", + ErrTypeMismatch, describeValue(value)) +} + +// metadataAnnotation names one annotation of one element: the element it +// annotates and its place among that element's annotations. +type metadataAnnotation struct { + element *symbols.Symbol + index int +} + +// metadataAnnotationDigest renders the annotation at that place as this context +// reads it: its metadata type and the text it states, so an annotation edited, +// reordered or retyped is not taken for the one an object was made for. The +// empty string says this context has no annotation there. +func (ctx *Context) metadataAnnotationDigest(element *symbols.Symbol, index int) string { + if ctx.model == nil || element == nil { + return "" + } + annotations := ctx.model.ElementMetadataOf(element) + if index < 0 || index >= len(annotations) { + return "" + } + annotation := annotations[index] + if annotation.Node == nil { + return "" + } + // An `about` annotation states itself away from the element it annotates, so + // the text comes from the document stating it. + return ctx.qualifiedSymbolName(annotation.Type) + " " + annotation.Doc + " " + + ctx.textIn(annotation.Doc, annotation.Node.Span()) +} + +// metadataInstance is the object one annotation denotes, of its metadata type, +// with the features its body binds set to the values they are bound to and the +// remaining ones keeping the defaults the type declares. One annotation denotes +// one object, so a second read of it answers the object the first made. +func (ec *EvalContext) metadataInstance(key metadataAnnotation, annotation semantics.ElementMetadata) (Value, error) { + ctx := ec.ctx + if id, held := ctx.metadataObjects[key]; held { + if _, live := ctx.instances[id]; live { + return Value{Kind: ValInstance, Instance: id}, nil + } + } + inst, err := ctx.materialize(annotation.Type, 0, nil, "") + if err != nil { + return Value{}, fmt.Errorf("metadata %s: %w", ctx.qualifiedSymbolName(annotation.Type), err) + } + if err := ec.bindMetadataFeatures(annotation.Type, inst, annotation.Bindings); err != nil { + return Value{}, err + } + ctx.metadataObjects[key] = inst.ID + return Value{Kind: ValInstance, Instance: inst.ID}, nil +} + +// bindMetadataFeatures writes the values one body level binds to the object it +// annotates, descending into the object a nested declaration writes through. +func (ec *EvalContext) bindMetadataFeatures(typ *symbols.Symbol, inst *Instance, bindings []semantics.MetadataBinding) error { + ctx := ec.ctx + name := ctx.qualifiedSymbolName(typ) + for _, binding := range bindings { + if fv, held := inst.FeatureValues[binding.Feature]; !held || fv == nil { + return fmt.Errorf("%w: metadata %s declares no feature %s", + ErrTypeMismatch, name, binding.Feature) + } + if binding.Value != nil { + // A value naming a sibling feature reads it off the object being bound. + val, err := NewEvalContextIn(ctx, binding.Scope, inst).Eval(binding.Value) + if err != nil { + return fmt.Errorf("metadata %s: %s: %w", name, binding.Feature, err) + } + if err := inst.SetFeatureValue(ctx, binding.Feature, val); err != nil { + return fmt.Errorf("metadata %s: %w", name, err) + } + } + if len(binding.Nested) == 0 { + continue + } + nested, err := ec.metadataNestedObject(typ, inst, binding.Feature) + if err != nil { + return err + } + if err := ec.bindMetadataFeatures(typ, nested, binding.Nested); err != nil { + return err + } + } + return nil +} + +// metadataNestedObject is the object a nested body level writes through: the one +// the named feature holds, which a feature holding a value rather than an object +// has none of. +func (ec *EvalContext) metadataNestedObject(typ *symbols.Symbol, inst *Instance, feature string) (*Instance, error) { + ctx := ec.ctx + name := ctx.qualifiedSymbolName(typ) + fv, err := inst.GetFeatureValue(ctx, feature) + if err != nil { + return nil, fmt.Errorf("metadata %s: %s: %w", name, feature, err) + } + id, isObject := fv.HeldValue().Object() + if !isObject { + return nil, fmt.Errorf("%w: metadata %s: feature %s holds no object to bind through", + ErrTypeMismatch, name, feature) + } + nested, live := ctx.instances[id] + if !live || nested == nil { + return nil, fmt.Errorf("%w: metadata %s: feature %s holds no object to bind through", + ErrTypeMismatch, name, feature) + } + return nested, nil +} diff --git a/internal/core/runtime/metadata_test.go b/internal/core/runtime/metadata_test.go new file mode 100644 index 000000000..61c851ff1 --- /dev/null +++ b/internal/core/runtime/metadata_test.go @@ -0,0 +1,689 @@ +package runtime + +import ( + "errors" + "fmt" + "slices" + "strings" + "testing" + + "github.com/Open-MBEE/OpenSysML/internal/core/parser" + "github.com/Open-MBEE/OpenSysML/internal/core/resolve" + "github.com/Open-MBEE/OpenSysML/internal/core/semantics" + "github.com/Open-MBEE/OpenSysML/internal/core/source" + "github.com/Open-MBEE/OpenSysML/internal/core/symbols" +) + +const metadataSrc = ` +package test { + private import ScalarValues::*; + + metadata def Safety { + attribute isMandatory : Boolean; + attribute level : Integer = 2; + } + + metadata def Legacy; + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + isMandatory = true; + } + @Legacy; + } + + part plain : Vehicle; + + attribute mass = 3; +} + +package about { + metadata test::Legacy about test::plain; +} +` + +// metadataTypeNames is the metadata type of every object in a `.metadata` sequence. +func metadataTypeNames(t *testing.T, ctx *Context, value Value) []string { + t.Helper() + if value.Kind != ValSequence { + t.Fatalf("metadata read as %v, want a sequence", value.Kind) + } + var names []string + for _, elem := range elementsOf(value) { + inst, ok := ctx.getInstance(elem.Instance) + if !ok { + t.Fatalf("element %v is no object", elem.Kind) + } + names = append(names, ctx.qualifiedSymbolName(inst.Type)) + } + return names +} + +// featureValue is what an object holds for the named feature. +func featureValue(t *testing.T, ctx *Context, inst *Instance, name string) Value { + t.Helper() + fv, err := inst.GetFeatureValue(ctx, name) + if err != nil { + t.Fatalf("feature %s: %v", name, err) + } + return fv.HeldValue() +} + +// TestMetadataAccessBoundValues reads the metadata of an annotated element: one +// object per annotation, in the order stated, carrying the values its body binds +// and the defaults its type declares. +func TestMetadataAccessBoundValues(t *testing.T) { + ctx, got, err := evalDeclaredExpr(t, metadataSrc, "test::seatBelt.metadata") + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + if want := []string{"test::Safety", "test::Legacy"}; !slices.Equal(metadataTypeNames(t, ctx, got), want) { + t.Errorf("metadata types = %v, want %v", metadataTypeNames(t, ctx, got), want) + } + safety, ok := ctx.getInstance(elementsOf(got)[0].Instance) + if !ok { + t.Fatal("the first metadata value is no object") + } + if v := featureValue(t, ctx, safety, "isMandatory"); FormatValue(v) != "true" { + t.Errorf("isMandatory = %s, want true", FormatValue(v)) + } + if v := featureValue(t, ctx, safety, "level"); FormatValue(v) != "2" { + t.Errorf("level = %s, want the declared default 2", FormatValue(v)) + } +} + +// TestMetadataAccessAboutForm reads metadata an `about` annotation states elsewhere. +func TestMetadataAccessAboutForm(t *testing.T) { + ctx, got, err := evalDeclaredExpr(t, metadataSrc, "test::plain.metadata") + if err != nil { + t.Fatalf("plain.metadata failed: %v", err) + } + if want := []string{"test::Legacy"}; !slices.Equal(metadataTypeNames(t, ctx, got), want) { + t.Errorf("metadata types = %v, want %v", metadataTypeNames(t, ctx, got), want) + } +} + +// TestMetadataAccessEmpty reads the metadata of an element nothing annotates. +func TestMetadataAccessEmpty(t *testing.T) { + for _, expr := range []string{"test::mass.metadata", "test::Vehicle.metadata"} { + ctx, got, err := evalDeclaredExpr(t, metadataSrc, expr) + if err != nil { + t.Fatalf("%s failed: %v", expr, err) + } + if names := metadataTypeNames(t, ctx, got); len(names) != 0 { + t.Errorf("%s = %v, want the empty sequence", expr, names) + } + } +} + +// TestMetadataAccessNotAnElement refuses `.metadata` read from a value. +func TestMetadataAccessNotAnElement(t *testing.T) { + for _, expr := range []string{"1.metadata", `"abc".metadata`, "(1 + 2).metadata"} { + _, _, err := evalDeclaredExpr(t, metadataSrc, expr) + if err == nil { + t.Fatalf("%s succeeded, want a typed error", expr) + } + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("%s: error %v, want a type mismatch", expr, err) + } + if !strings.Contains(err.Error(), "metadata access requires an element") { + t.Errorf("%s: error %q, want it to require an element", expr, err) + } + } +} + +// TestMetadataAccessUnresolved refuses `.metadata` over a name that names nothing. +func TestMetadataAccessUnresolved(t *testing.T) { + _, _, err := evalDeclaredExpr(t, metadataSrc, "test::nope.metadata") + if !errors.Is(err, ErrUnresolvedReference) { + t.Errorf("error %v, want an unresolved reference", err) + } +} + +// TestMetadataAccessUnknownFeature refuses a body binding the metadata type declares +// no feature for, rather than dropping the value. +func TestMetadataAccessUnknownFeature(t *testing.T) { + src := ` +package test { + metadata def Safety { + attribute level : ScalarValues::Integer = 2; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + severity = 3; + } + } +} +` + _, _, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err == nil { + t.Fatal("an unknown metadata feature succeeded, want a typed error") + } + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("error %v, want a type mismatch", err) + } + if !strings.Contains(err.Error(), "severity") { + t.Errorf("error %q, want it to name severity", err) + } +} + +// TestMetadataAccessFailureAbandonsInstances requires one access to materialize +// every annotation or none: an annotation that fails leaves behind no object, +// and no behavior of one, of the annotations read before it. +func TestMetadataAccessFailureAbandonsInstances(t *testing.T) { + src := ` +package test { + part def Controller { + attribute count : ScalarValues::Integer = 0; + exhibit state modes { + entry; then running; + state running { + entry action bump { assign count := count + 1; } + } + } + } + + part ctrl : Controller; + + metadata def Safety { + attribute level : ScalarValues::Integer = 2; + } + + part def Vehicle; + + part reader : Vehicle { + @Safety { + level = ctrl.count; + } + } + + part seatBelt : Vehicle { + @Safety { + level = ctrl.count; + } + @Safety { + severity = 3; + } + } +} +` + // The first annotation reads an object whose machine runs, so the failing + // access has behaviors as well as objects to abandon. + ok, _, err := evalDeclaredExpr(t, src, "test::reader.metadata") + if err != nil { + t.Fatalf("test::reader.metadata: %v", err) + } + if len(ok.objectBehaviors) == 0 { + t.Fatal("reading the annotation started no behavior, so the test proves nothing") + } + + ctx, _, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err == nil { + t.Fatal("the failing annotation succeeded, want a typed error") + } + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("error %v, want a type mismatch", err) + } + if live := len(ctx.instances); live != 0 { + t.Errorf("%d object(s) outlived the failed access, want none", live) + } + if created := len(ctx.created); created != 0 { + t.Errorf("%d object(s) stay registered as created, want none", created) + } + if attached, pending := len(ctx.objectBehaviors), len(ctx.pendingBehaviors); attached != 0 || pending != 0 { + t.Errorf("%d behavior(s) (%d pending) outlived the failed access, want none", attached, pending) + } +} + +// TestMetadataAccessNestedBindings reads an annotation whose body binds a value +// through a nested declaration: the object the outer feature holds carries it. +func TestMetadataAccessNestedBindings(t *testing.T) { + src := ` +package test { + private import ScalarValues::*; + + metadata def Cause { + attribute code : Integer = 0; + } + + metadata def Risk { + attribute level : Integer = 0; + attribute note : String = "none"; + attribute cause : Cause; + } + + metadata def Safety { + attribute risk : Risk; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + risk { + level = 7; + cause { + code = 42; + } + } + } + } +} +` + ctx, got, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + safety, ok := ctx.getInstance(elementsOf(got)[0].Instance) + if !ok { + t.Fatal("the metadata value is no object") + } + id, isObject := featureValue(t, ctx, safety, "risk").Object() + if !isObject { + t.Fatal("risk holds no object") + } + risk, ok := ctx.getInstance(id) + if !ok { + t.Fatal("the object risk holds is not live") + } + if v := featureValue(t, ctx, risk, "level"); FormatValue(v) != "7" { + t.Errorf("risk.level = %s, want the nested binding 7", FormatValue(v)) + } + if v := featureValue(t, ctx, risk, "note"); FormatValue(v) != `"none"` { + t.Errorf("risk.note = %s, want the declared default", FormatValue(v)) + } + causeID, isObject := featureValue(t, ctx, risk, "cause").Object() + if !isObject { + t.Fatal("cause holds no object") + } + cause, ok := ctx.getInstance(causeID) + if !ok { + t.Fatal("the object cause holds is not live") + } + if v := featureValue(t, ctx, cause, "code"); FormatValue(v) != "42" { + t.Errorf("risk.cause.code = %s, want the nested binding 42", FormatValue(v)) + } +} + +// TestMetadataAccessBindingScope reads a body value naming a feature of the +// metadata type that an element around the annotation also names: the body sees +// the metadata type's own member. +func TestMetadataAccessBindingScope(t *testing.T) { + src := ` +package test { + private import ScalarValues::*; + + attribute limit = 1; + + metadata def Safety { + attribute limit : Integer = 9; + attribute level : Integer = 0; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + level = limit; + } + } +} +` + ctx, got, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + safety, ok := ctx.getInstance(elementsOf(got)[0].Instance) + if !ok { + t.Fatal("the metadata value is no object") + } + if v := featureValue(t, ctx, safety, "level"); FormatValue(v) != "9" { + t.Errorf("level = %s, want 9, the limit the metadata type declares", FormatValue(v)) + } +} + +// TestMetadataAccessRenamedRedefinition binds a metadata feature through a +// redefinition that gives it a name of its own, at both body levels. +func TestMetadataAccessRenamedRedefinition(t *testing.T) { + src := ` +package test { + private import ScalarValues::*; + + metadata def Cause { + attribute code : Integer = 0; + } + + metadata def Safety { + attribute level : Integer = 0; + attribute cause : Cause; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + attribute severity :>> level = 3; + cause { + attribute reason :>> code = 42; + } + } + } +} +` + ctx, got, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + safety, ok := ctx.getInstance(elementsOf(got)[0].Instance) + if !ok { + t.Fatal("the metadata value is no object") + } + if v := featureValue(t, ctx, safety, "level"); FormatValue(v) != "3" { + t.Errorf("level = %s, want the redefining binding 3", FormatValue(v)) + } + id, isObject := featureValue(t, ctx, safety, "cause").Object() + if !isObject { + t.Fatal("cause holds no object") + } + cause, ok := ctx.getInstance(id) + if !ok { + t.Fatal("the object cause holds is not live") + } + if v := featureValue(t, ctx, cause, "code"); FormatValue(v) != "42" { + t.Errorf("cause.code = %s, want the redefining binding 42", FormatValue(v)) + } +} + +// TestMetadataAccessDependentBindings reads a body value naming a feature an +// earlier binding of the same body bound: it reads what was bound, not the +// default the metadata type declares. +func TestMetadataAccessDependentBindings(t *testing.T) { + src := ` +package test { + private import ScalarValues::*; + + metadata def Safety { + attribute level : Integer = 0; + attribute margin : Integer = 0; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + level = 2; + margin = level + 1; + } + } +} +` + ctx, got, err := evalDeclaredExpr(t, src, "test::seatBelt.metadata") + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + safety, ok := ctx.getInstance(elementsOf(got)[0].Instance) + if !ok { + t.Fatal("the metadata value is no object") + } + if v := featureValue(t, ctx, safety, "margin"); FormatValue(v) != "3" { + t.Errorf("margin = %s, want 3, one more than the level bound before it", FormatValue(v)) + } +} + +// TestMetadataAccessSameObjects reads the metadata of one element twice: an +// annotation denotes one object, so both reads answer it and no second object +// of the metadata type is made. +func TestMetadataAccessSameObjects(t *testing.T) { + src := ` +package test { + private import ScalarValues::*; + + metadata def Safety { + attribute level : Integer = 0; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + level = 3; + } + } +} +` + ctx, scope, decl := declaredExpr(t, src, "test::seatBelt.metadata") + first, err := NewEvalContext(ctx, scope).Eval(decl) + if err != nil { + t.Fatalf("seatBelt.metadata failed: %v", err) + } + made := len(ctx.instances) + second, err := NewEvalContext(ctx, scope).Eval(decl) + if err != nil { + t.Fatalf("the second seatBelt.metadata failed: %v", err) + } + one, two := elementsOf(first), elementsOf(second) + if len(one) != 1 || len(two) != 1 { + t.Fatalf("read %d then %d metadata values, want one each", len(one), len(two)) + } + if one[0].Instance != two[0].Instance { + t.Errorf("the reads answered objects %d and %d, want one object", one[0].Instance, two[0].Instance) + } + if len(ctx.instances) != made { + t.Errorf("the second read left %d objects, want the %d the first did", len(ctx.instances), made) + } +} + +const adoptMetadataSrc = `package Demo { + metadata def Safety { attribute level = 3; } + part def Vehicle; + part seatBelt : Vehicle { + @Safety { + level = 5; + } + } + part def Holder { attribute mark; } + part def Reader { attribute seen = seatBelt.metadata; } +}` + +// TestAdoptKeepsTheObjectAnAnnotationDenotes carries an object holding what an +// annotation denotes into a re-analysis: the annotation still denotes that +// object there, so reading it again answers it rather than making a second one. +func TestAdoptKeepsTheObjectAnAnnotationDenotes(t *testing.T) { + prev := contextOver(t, adoptMetadataSrc) + reader, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + fv, err := reader.GetFeatureValue(prev, "seen") + if err != nil { + t.Fatalf("GetFeatureValue(seen): %v", err) + } + holder, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Holder")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + if err := holder.SetFeatureValue(prev, "mark", fv.Value); err != nil { + t.Fatalf("SetFeatureValue(mark): %v", err) + } + carried := elementsOf(fv.Value) + if len(carried) != 1 { + t.Fatalf("mark holds %d metadata values, want one", len(carried)) + } + shapes := prev.ShapesOf(holder) + + ctx := contextOver(t, adoptMetadataSrc+"\npart def Widget;") + if _, err := ctx.Adopt(prev, shapes, holder); err != nil { + t.Fatalf("Adopt: %v", err) + } + if _, found := ctx.Instance(carried[0].Instance); !found { + t.Fatalf("the metadata object %d was not carried over, so the test proves nothing", + carried[0].Instance) + } + made := len(ctx.instances) + again, err := ctx.Instantiate(lookupOne(t, ctx.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate after adoption: %v", err) + } + seen, err := again.GetFeatureValue(ctx, "seen") + if err != nil { + t.Fatalf("GetFeatureValue(seen) after adoption: %v", err) + } + read := elementsOf(seen.Value) + if len(read) != 1 { + t.Fatalf("the annotation reads as %d metadata values after adoption, want one", len(read)) + } + if read[0].Instance != carried[0].Instance { + t.Errorf("the annotation denotes object %d after adoption, want the carried %d", + read[0].Instance, carried[0].Instance) + } + if len(ctx.instances) != made+1 { + t.Errorf("reading the annotation again left %d objects, want the %d carried plus the reader", + len(ctx.instances), made) + } +} + +// TestAdoptReadsAChangedAnnotationAgain edits the annotation body between the +// two analyses: the object made for what it said before does not stand for what +// it says now, so the annotation is read again and answers the new value. +func TestAdoptReadsAChangedAnnotationAgain(t *testing.T) { + prev := contextOver(t, adoptMetadataSrc) + reader, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + fv, err := reader.GetFeatureValue(prev, "seen") + if err != nil { + t.Fatalf("GetFeatureValue(seen): %v", err) + } + holder, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Holder")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + if err := holder.SetFeatureValue(prev, "mark", fv.Value); err != nil { + t.Fatalf("SetFeatureValue(mark): %v", err) + } + carried := elementsOf(fv.Value) + if len(carried) != 1 { + t.Fatalf("the annotation reads as %d metadata values, want one", len(carried)) + } + shapes := prev.ShapesOf(holder) + + ctx := contextOver(t, strings.Replace(adoptMetadataSrc, "level = 5", "level = 9", 1)) + if _, err := ctx.Adopt(prev, shapes, holder); err != nil { + t.Fatalf("Adopt: %v", err) + } + again, err := ctx.Instantiate(lookupOne(t, ctx.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate after adoption: %v", err) + } + seen, err := again.GetFeatureValue(ctx, "seen") + if err != nil { + t.Fatalf("GetFeatureValue(seen) after adoption: %v", err) + } + read := elementsOf(seen.Value) + if len(read) != 1 { + t.Fatalf("the annotation reads as %d metadata values after adoption, want one", len(read)) + } + if read[0].Instance == carried[0].Instance { + t.Fatalf("the edited annotation reused object %d, made for what it said before", + carried[0].Instance) + } + obj, found := ctx.Instance(read[0].Instance) + if !found { + t.Fatalf("the annotation reads as object %d, which the context does not hold", read[0].Instance) + } + level, err := obj.GetFeatureValue(ctx, "level") + if err != nil { + t.Fatalf("GetFeatureValue(level): %v", err) + } + if got := fmt.Sprint(level.Value.Const); !strings.Contains(got, "9") { + t.Errorf("level = %s, want the 9 the annotation states now", got) + } +} + +// contextOverDocs indexes each named document and gives the context every text, +// so a digest over an annotation reads the document stating it. +func contextOverDocs(t *testing.T, docs [][2]string) *Context { + t.Helper() + idx := symbols.NewIndex() + for _, doc := range docs { + idx.AddDocument(doc[0], parser.New(source.New(doc[0], []byte(doc[1]))).ParseFile()) + } + resolver := resolve.New(idx) + ctx := NewContext(semantics.NewModel(resolver), resolver, 10000) + for _, doc := range docs { + ctx.RegisterSource(source.New(doc[0], []byte(doc[1]))) + } + return ctx +} + +const adoptAboutModel = `package Demo { + metadata def Safety { attribute level = 3; } + part def Vehicle; + part seatBelt : Vehicle; + part def Holder { attribute mark; } + part def Reader { attribute seen = seatBelt.metadata; } +}` + +const adoptAboutNotes = `package Notes { + metadata Demo::Safety about Demo::seatBelt { + level = 5; + } +}` + +// TestAdoptReadsAChangedAboutAnnotationAgain states the annotation away from the +// element it annotates: editing the annotating document is what makes the object +// made for it stale, and editing the annotated element's document does not. +func TestAdoptReadsAChangedAboutAnnotationAgain(t *testing.T) { + read := func(t *testing.T, ctx *Context, obj *Instance) Value { + t.Helper() + fv, err := obj.GetFeatureValue(ctx, "seen") + if err != nil { + t.Fatalf("GetFeatureValue(seen): %v", err) + } + vals := elementsOf(fv.Value) + if len(vals) != 1 { + t.Fatalf("the annotation reads as %d metadata values, want one", len(vals)) + } + return vals[0] + } + carry := func(t *testing.T, model, notes string) (int64, int64) { + t.Helper() + prev := contextOverDocs(t, [][2]string{{"model.sysml", adoptAboutModel}, {"notes.sysml", adoptAboutNotes}}) + reader, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + before := read(t, prev, reader) + holder, err := prev.Instantiate(lookupOne(t, prev.resolver.Index(), "Demo::Holder")) + if err != nil { + t.Fatalf("Instantiate: %v", err) + } + if err := holder.SetFeatureValue(prev, "mark", before); err != nil { + t.Fatalf("SetFeatureValue(mark): %v", err) + } + ctx := contextOverDocs(t, [][2]string{{"model.sysml", model}, {"notes.sysml", notes}}) + if _, err := ctx.Adopt(prev, prev.ShapesOf(holder), holder); err != nil { + t.Fatalf("Adopt: %v", err) + } + again, err := ctx.Instantiate(lookupOne(t, ctx.resolver.Index(), "Demo::Reader")) + if err != nil { + t.Fatalf("Instantiate after adoption: %v", err) + } + return before.Instance, read(t, ctx, again).Instance + } + + before, after := carry(t, adoptAboutModel+"\npart def Widget;", adoptAboutNotes) + if before != after { + t.Errorf("an unedited annotation read as object %d, want the %d it denoted", after, before) + } + before, after = carry(t, adoptAboutModel, strings.Replace(adoptAboutNotes, "level = 5", "level = 9", 1)) + if before == after { + t.Errorf("the edited annotation reused object %d, made for what it said before", before) + } +} diff --git a/internal/core/runtime/robustness_test.go b/internal/core/runtime/robustness_test.go index fd340bf09..a0d048450 100644 --- a/internal/core/runtime/robustness_test.go +++ b/internal/core/runtime/robustness_test.go @@ -183,6 +183,10 @@ func TestRuntimeRobustness(t *testing.T) { t.Run("operation_of_a_destroyed_object", testOperationOfADestroyedObject) t.Run("structured_attribute_chain_of_an_unknown_feature", testStructuredAttributeChainOfAnUnknownFeature) t.Run("elements_chain_of_a_non_numeric_collection", testElementsChainOfANonNumericCollection) + t.Run("arithmetic_over_the_unbounded_value", testArithmeticOverTheUnboundedValue) + t.Run("unbounded_value_compared_with_a_string", testUnboundedValueComparedWithAString) + t.Run("metadata_of_a_value", testMetadataOfAValue) + t.Run("metadata_of_an_unresolved_name", testMetadataOfAnUnresolvedName) t.Run("constraint_missing_feature", testConstraintMissingFeature) t.Run("nested_condition_subject_is_ambiguous", testNestedConditionSubjectIsAmbiguous) t.Run("satisfaction_subject_is_ambiguous", testSatisfactionSubjectIsAmbiguous) @@ -11440,3 +11444,41 @@ func testVerificationWithAnArgumentTheCaseDoesNotTake(t *testing.T) { t.Fatalf("error = %v, want ErrUnknownParameter", err) } } + +// testArithmeticOverTheUnboundedValue: `*` is no number, so arithmetic over it +// fails with a typed error naming the operation. +func testArithmeticOverTheUnboundedValue(t *testing.T) { + for _, expr := range []string{"* + 1", "1 - *", "2 * *", "* / 2", "* % 2", "* ** 2", "-*", "+*"} { + _, _, err := evalDeclaredExpr(t, "package test {}", expr) + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("%s: error = %v, want ErrTypeMismatch", expr, err) + } + } +} + +// testUnboundedValueComparedWithAString: nothing orders `*` against a string. +func testUnboundedValueComparedWithAString(t *testing.T) { + _, _, err := evalDeclaredExpr(t, "package test {}", `* > "a"`) + if !errors.Is(err, ErrTypeMismatch) { + t.Fatalf("error = %v, want ErrTypeMismatch", err) + } +} + +// testMetadataOfAValue: only an element carries metadata, so reading it from a +// scalar fails rather than answering with the empty sequence. +func testMetadataOfAValue(t *testing.T) { + for _, expr := range []string{"1.metadata", `"abc".metadata`} { + _, _, err := evalDeclaredExpr(t, "package test {}", expr) + if !errors.Is(err, ErrTypeMismatch) { + t.Errorf("%s: error = %v, want ErrTypeMismatch", expr, err) + } + } +} + +// testMetadataOfAnUnresolvedName: a name that names no element is refused. +func testMetadataOfAnUnresolvedName(t *testing.T) { + _, _, err := evalDeclaredExpr(t, "package test {}", "test::missing.metadata") + if !errors.Is(err, ErrUnresolvedReference) { + t.Fatalf("error = %v, want ErrUnresolvedReference", err) + } +} diff --git a/internal/core/runtime/testdata/conformance/README.md b/internal/core/runtime/testdata/conformance/README.md index a3a80be2c..5c2bb7527 100644 --- a/internal/core/runtime/testdata/conformance/README.md +++ b/internal/core/runtime/testdata/conformance/README.md @@ -311,6 +311,8 @@ Supported types: - `Boolean`: JSON boolean - `String`: JSON string - `Null`: JSON null +- `Infinity`: the unbounded `*`, which is no number and carries no `value` + (`{"type": "Infinity"}`) - `Quantity`: JSON number, with the `unit` the magnitude is written in - `MeasurementRef`: the `unit` a measurement reference names, and no `value` (`{"type": "MeasurementRef", "unit": "m**2"}`) diff --git a/internal/core/runtime/testdata/conformance/metadata_access_annotations.expected.json b/internal/core/runtime/testdata/conformance/metadata_access_annotations.expected.json new file mode 100644 index 000000000..9b6c21dc2 --- /dev/null +++ b/internal/core/runtime/testdata/conformance/metadata_access_annotations.expected.json @@ -0,0 +1,13 @@ +{ + "type": "instance", + "instantiate": "test::Report", + "libraries": true, + "slots": { + "annotations": {"type": "Sequence", "elements": [{"type": "Instance"}, {"type": "Instance"}]}, + "mandatory": {"type": "Boolean", "value": true}, + "level": {"type": "Integer", "value": 4}, + "superseded": {"type": "String", "value": "none"}, + "defaulted": {"type": "Integer", "value": 2}, + "none": {"type": "Sequence", "elements": []} + } +} diff --git a/internal/core/runtime/testdata/conformance/metadata_access_annotations.sysml b/internal/core/runtime/testdata/conformance/metadata_access_annotations.sysml new file mode 100644 index 000000000..7c43030fd --- /dev/null +++ b/internal/core/runtime/testdata/conformance/metadata_access_annotations.sysml @@ -0,0 +1,40 @@ +// `.metadata` (KerML 8.3.3.1 MetadataAccessExpression) reads the metadata +// annotating an element: one object per annotation, in the order stated, +// carrying the values its body binds over the defaults its type declares. +package test { + private import ScalarValues::*; + + metadata def Safety { + attribute isMandatory : Boolean; + attribute level : Integer = 2; + } + + metadata def Legacy { + attribute supersededBy : String = "none"; + } + + part def Vehicle; + + part seatBelt : Vehicle { + @Safety { + isMandatory = true; + level = 4; + } + @Legacy; + } + + part airbag : Vehicle { + @Safety; + } + + part chassis : Vehicle; + + part def Report { + attribute annotations [*] = seatBelt.metadata; + attribute mandatory = seatBelt.metadata#(1).isMandatory; + attribute level = seatBelt.metadata#(1).level; + attribute superseded = seatBelt.metadata#(2).supersededBy; + attribute defaulted = airbag.metadata#(1).level; + attribute none [*] = chassis.metadata; + } +} diff --git a/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.expected.json b/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.expected.json new file mode 100644 index 000000000..e30882143 --- /dev/null +++ b/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.expected.json @@ -0,0 +1,16 @@ +{ + "type": "instance", + "instantiate": "test::Arithmetic", + "libraries": true, + "slots": { + "sum": {"error": "operator '+' is not defined for the unbounded value '*': * + 1"}, + "addedTo": {"error": "operator '+' is not defined for the unbounded value '*': 1 + *"}, + "difference": {"error": "operator '-' is not defined for the unbounded value '*': * - 1"}, + "product": {"error": "operator '*' is not defined for the unbounded value '*': 2 * *"}, + "quotient": {"error": "operator '/' is not defined for the unbounded value '*': * / 2"}, + "remainder": {"error": "operator '%' is not defined for the unbounded value '*': * % 2"}, + "power": {"error": "operator '**' is not defined for the unbounded value '*': * ** 2"}, + "negated": {"error": "unary '-' is not defined for *"}, + "positive": {"error": "unary '+' is not defined for *"} + } +} diff --git a/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.sysml b/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.sysml new file mode 100644 index 000000000..7e1b749f0 --- /dev/null +++ b/internal/core/runtime/testdata/conformance/value_unbounded_arithmetic_refused.sysml @@ -0,0 +1,17 @@ +// `*` is no number, so arithmetic over it is refused with an error naming the +// operation rather than answered with a finite result. +package test { + private import ScalarValues::*; + + part def Arithmetic { + attribute sum = * + 1; + attribute addedTo = 1 + *; + attribute difference = * - 1; + attribute product = 2 * *; + attribute quotient = * / 2; + attribute remainder = * % 2; + attribute power = * ** 2; + attribute negated = -*; + attribute positive = +*; + } +} diff --git a/internal/core/runtime/testdata/conformance/value_unbounded_comparison.expected.json b/internal/core/runtime/testdata/conformance/value_unbounded_comparison.expected.json new file mode 100644 index 000000000..471696b73 --- /dev/null +++ b/internal/core/runtime/testdata/conformance/value_unbounded_comparison.expected.json @@ -0,0 +1,17 @@ +{ + "type": "instance", + "instantiate": "test::Bounds", + "libraries": true, + "slots": { + "unbounded": {"type": "Infinity"}, + "exceedsNatural": {"type": "Boolean", "value": true}, + "exceedsInteger": {"type": "Boolean", "value": true}, + "exceedsReal": {"type": "Boolean", "value": true}, + "belowUnbounded": {"type": "Boolean", "value": true}, + "equalsItself": {"type": "Boolean", "value": true}, + "atMostItself": {"type": "Boolean", "value": true}, + "aboveItself": {"type": "Boolean", "value": false}, + "atMostFinite": {"type": "Boolean", "value": false}, + "differsFromFinite": {"type": "Boolean", "value": true} + } +} diff --git a/internal/core/runtime/testdata/conformance/value_unbounded_comparison.sysml b/internal/core/runtime/testdata/conformance/value_unbounded_comparison.sysml new file mode 100644 index 000000000..6e1318b76 --- /dev/null +++ b/internal/core/runtime/testdata/conformance/value_unbounded_comparison.sysml @@ -0,0 +1,18 @@ +// `*` (KerML 8.3.3.1 LiteralInfinity) is a value of its own: it exceeds every +// finite number, whatever its type, and equals itself. +package test { + private import ScalarValues::*; + + part def Bounds { + attribute unbounded = *; + attribute exceedsNatural = * > 1000000; + attribute exceedsInteger = * > -3; + attribute exceedsReal = * > 1.5e10; + attribute belowUnbounded = 42 < *; + attribute equalsItself = * == *; + attribute atMostItself = * <= *; + attribute aboveItself = * > *; + attribute atMostFinite = * <= 7; + attribute differsFromFinite = * != 7; + } +} diff --git a/internal/core/semantics/annotations.go b/internal/core/semantics/annotations.go index 9c18a55e5..333561881 100644 --- a/internal/core/semantics/annotations.go +++ b/internal/core/semantics/annotations.go @@ -123,6 +123,89 @@ func (m *Model) AnnotationSitesOf(sym *symbols.Symbol) []AnnotationSite { return out } +// MetadataBinding is one feature an annotation body binds: the value it is bound +// to, if any, and the bindings its own body nests under it. +type MetadataBinding struct { + Feature string + Value ast.Node + // Scope is where the value resolves names: the body's own scope, which sees + // the metadata type's members before those around the annotated element. + Scope *symbols.Scope + Nested []MetadataBinding +} + +// ElementMetadata is one metadata annotation of an element as `.metadata` reads +// it: the metadata type to materialize and the values its body binds. Values +// the body leaves unbound come from the type's own declarations. +type ElementMetadata struct { + Type *symbols.Symbol + Node ast.Node + // Doc is the document stating the annotation, which an `about` form states + // away from the element it annotates. + Doc string + About bool + Bindings []MetadataBinding +} + +// ElementMetadataOf returns the metadata annotating sym, inline annotations +// first and `about`-form ones after, each in declaration order — the same side +// table an element filter classifies by. +func (m *Model) ElementMetadataOf(sym *symbols.Symbol) []ElementMetadata { + var out []ElementMetadata + for _, a := range m.annotationsOf(sym) { + if a.typ == nil || a.node == nil { + continue + } + out = append(out, ElementMetadata{ + Type: a.typ, + Node: a.node, + Doc: symbols.DocNameOf(a.scope), + About: a.about, + Bindings: metadataBindings(valueScope(a.scope, a.node), metadataBody(a.node)), + }) + } + return out +} + +// metadataBody is the body an annotation node binds feature values in. +func metadataBody(node ast.Node) []ast.Node { + switch n := node.(type) { + case *ast.PrefixMetadata: + return n.Body + case *ast.Usage: + return n.Members + default: + return nil + } +} + +// metadataBindings is the features an annotation body binds, in declaration +// order, each with the bindings its own body states under it. +func metadataBindings(scope *symbols.Scope, body []ast.Node) []MetadataBinding { + var out []MetadataBinding + for _, member := range body { + usage := metadataBodyFeature(member) + if usage == nil { + continue + } + name := redefinedFeatureName(usage) + if name == "" { + continue + } + nested := metadataBindings(valueScope(scope, usage), usage.Members) + if usage.Value == nil && len(nested) == 0 { + continue + } + out = append(out, MetadataBinding{ + Feature: name, + Value: usage.Value, + Scope: scope, + Nested: nested, + }) + } + return out +} + // sortedFeatureNames orders an annotation's bound features by name, so that what // is reported does not depend on map iteration order. func sortedFeatureNames(values map[string]symbols.FilterValue) []string { @@ -266,7 +349,15 @@ func bodyScope(_ *ast.Usage, declared *symbols.Scope) *symbols.Scope { return de // aboutAnnotations returns the annotations that `metadata m about sym;` // declarations elsewhere in the workspace state about sym. func (m *Model) aboutAnnotations(sym *symbols.Symbol) []annotation { - return m.annotationsAbout()[sym] + if out, ok := m.annotationsAbout()[sym]; ok { + return out + } + // The caller may hold a symbol re-indexed from the same declaration as the + // one indexed here, which the declaration identifies across both trees. + if sym.Decl == nil { + return nil + } + return m.aboutByDecl[sym.Decl] } // AboutAnnotatedSymbols returns every element an `about` metadata usage @@ -286,6 +377,7 @@ func (m *Model) annotationsAbout() map[*symbols.Symbol][]annotation { return m.aboutAnnots } m.aboutAnnots = make(map[*symbols.Symbol][]annotation) + m.aboutByDecl = make(map[ast.Node][]annotation) idx := m.resolver.Index() if idx == nil { return m.aboutAnnots @@ -345,6 +437,9 @@ func (m *Model) indexAboutUsage(sym *symbols.Symbol) { m.aboutOrder = append(m.aboutOrder, target) } m.aboutAnnots[target] = append(m.aboutAnnots[target], a) + if target.Decl != nil { + m.aboutByDecl[target.Decl] = append(m.aboutByDecl[target.Decl], a) + } } } @@ -400,6 +495,20 @@ func boundFeatureName(u *ast.Usage) string { if u.Ident.Name != "" { return u.Ident.Name } + return redefinitionTargetName(u) +} + +// redefinedFeatureName is the metadata feature a body member writes to: the one +// it redefines, which a name of its own renames rather than replaces. +func redefinedFeatureName(u *ast.Usage) string { + if name := redefinitionTargetName(u); name != "" { + return name + } + return u.Ident.Name +} + +// redefinitionTargetName is the feature a `:>> f` clause names, or "". +func redefinitionTargetName(u *ast.Usage) string { for _, rel := range u.Relationships { if rel == nil || rel.Kind != ast.RelRedefines { continue diff --git a/internal/core/semantics/eval.go b/internal/core/semantics/eval.go index ad09e4409..f6e59951b 100644 --- a/internal/core/semantics/eval.go +++ b/internal/core/semantics/eval.go @@ -125,6 +125,38 @@ func (v Value) WholeNumber() (int64, bool) { return 0, false } +// IsUnbounded reports whether the value is the unbounded `*`. +func (v Value) IsUnbounded() bool { return v.Kind == ValInfinity } + +// UnboundedOrder compares l and r where at least one is the unbounded `*`: `*` +// exceeds every finite number and equals itself. ok is false when the other +// operand is neither a number nor `*`, since nothing orders it against one. +func UnboundedOrder(l, r Value) (order int, ok bool) { + ordinal := func(v Value) (int, bool) { + switch { + case v.IsUnbounded(): + return 1, true + case v.IsNumeric(): + return 0, true + default: + return 0, false + } + } + lo, lok := ordinal(l) + ro, rok := ordinal(r) + if !lok || !rok { + return 0, false + } + switch { + case lo == ro: + return 0, true + case lo > ro: + return 1, true + default: + return -1, true + } +} + // AsReal returns the value as a float64 (int and real only). func (v Value) AsReal() float64 { if v.Kind == ValInt { @@ -382,6 +414,12 @@ func evalEquality(op ast.OperatorKind, l, r Value) (Value, bool) { switch { case l.Kind == ValBool && r.Kind == ValBool: eq = l.Bool == r.Bool + case l.IsUnbounded() || r.IsUnbounded(): + order, ok := UnboundedOrder(l, r) + if !ok { + return Value{}, false + } + eq = order == 0 case l.IsNumeric() && r.IsNumeric(): eq = l.AsReal() == r.AsReal() default: @@ -394,6 +432,17 @@ func evalEquality(op ast.OperatorKind, l, r Value) (Value, bool) { } func evalComparison(op ast.OperatorKind, l, r Value) (Value, bool) { + if l.IsUnbounded() || r.IsUnbounded() { + order, ok := UnboundedOrder(l, r) + if !ok { + return Value{}, false + } + res, ok := OrderSatisfies(op, order) + if !ok { + return Value{}, false + } + return Value{Kind: ValBool, Bool: res}, true + } if !l.IsNumeric() || !r.IsNumeric() { return Value{}, false } @@ -412,6 +461,23 @@ func evalComparison(op ast.OperatorKind, l, r Value) (Value, bool) { return Value{Kind: ValBool, Bool: res}, true } +// OrderSatisfies applies an ordering operator to a comparison result of -1, 0 +// or 1. ok is false for an operator that is no ordering. +func OrderSatisfies(op ast.OperatorKind, order int) (res, ok bool) { + switch op { + case ast.OpLt: + return order < 0, true + case ast.OpLe: + return order <= 0, true + case ast.OpGt: + return order > 0, true + case ast.OpGe: + return order >= 0, true + default: + return false, false + } +} + func evalArithmetic(op ast.OperatorKind, l, r Value) (Value, bool) { if !l.IsNumeric() || !r.IsNumeric() { return Value{}, false diff --git a/internal/core/semantics/model.go b/internal/core/semantics/model.go index ab6ae5550..d2717c4d5 100644 --- a/internal/core/semantics/model.go +++ b/internal/core/semantics/model.go @@ -71,6 +71,9 @@ type Model struct { filterTypes map[string]*symbols.Symbol annotations map[*symbols.Symbol][]annotation aboutAnnots map[*symbols.Symbol][]annotation + // aboutByDecl keys the same annotations by the declaration of the element + // annotated, reaching them from a re-indexed twin of that symbol. + aboutByDecl map[ast.Node][]annotation // aboutOrder lists aboutAnnots' targets in first-annotation order. aboutOrder []*symbols.Symbol diff --git a/internal/core/semantics/quantity.go b/internal/core/semantics/quantity.go index f6314804b..3a2ca63f8 100644 --- a/internal/core/semantics/quantity.go +++ b/internal/core/semantics/quantity.go @@ -117,7 +117,7 @@ func FormatConst(c Value) string { case ValBool: return strconv.FormatBool(c.Bool) case ValInfinity: - return "∞" + return "*" default: return "" } diff --git a/internal/core/semantics/valuetype.go b/internal/core/semantics/valuetype.go index c61f6c842..f278d66d3 100644 --- a/internal/core/semantics/valuetype.go +++ b/internal/core/semantics/valuetype.go @@ -17,6 +17,7 @@ const ( fqnString = "ScalarValues::String" fqnNatural = "ScalarValues::Natural" + fqnPositive = "ScalarValues::Positive" fqnInteger = "ScalarValues::Integer" fqnRational = "ScalarValues::Rational" fqnReal = "ScalarValues::Real" @@ -103,6 +104,9 @@ func (m *Model) exprConformance(scope *symbols.Scope, node ast.Node, want *symbo return m.typeConformance(m.libSymbol(fqnNatural), want) case *ast.LiteralReal: return m.typeConformance(m.libSymbol(fqnRational), want) + case *ast.LiteralInfinity: + // `*` is the natural number exceeding every other (KerML 8.4.4.6). + return m.typeConformance(m.libSymbol(fqnPositive), want) case *ast.FeatureReference, *ast.QualifiedName, *ast.FeatureChainExpr: sym, ok := m.resolver.ResolveTarget(scope, n) if !ok || sym == nil { diff --git a/internal/core/solve/pin.go b/internal/core/solve/pin.go index eeb68e852..eabcf9c9d 100644 --- a/internal/core/solve/pin.go +++ b/internal/core/solve/pin.go @@ -558,7 +558,7 @@ func constText(c semantics.Value) string { case semantics.ValBool: return strconv.FormatBool(c.Bool) case semantics.ValInfinity: - return "∞" + return "*" default: return "" } diff --git a/internal/grpc/capability_response.go b/internal/grpc/capability_response.go index c8651db28..50346189f 100644 --- a/internal/grpc/capability_response.go +++ b/internal/grpc/capability_response.go @@ -93,6 +93,10 @@ func (s *Service) filterValueCapabilities(value *pb.Value) { shown := displayValue(value) value.Kind = &pb.Value_Null{Null: "unsupported: " + shown.Kind.String() + " " + runtime.FormatValue(shown)} } + case *pb.Value_Infinity: + if !s.capabilities.has(CapabilityInfinityValue) { + value.Kind = &pb.Value_Null{Null: "unsupported: unbounded value *"} + } } } diff --git a/internal/grpc/convert.go b/internal/grpc/convert.go index 09b4fd013..2fc094f9a 100644 --- a/internal/grpc/convert.go +++ b/internal/grpc/convert.go @@ -250,7 +250,7 @@ func ValueToProtoIn(rt *runtime.Context, val runtime.Value, idx *symbols.Index) case semantics.ValBool: return &pb.Value{Kind: &pb.Value_BoolValue{BoolValue: val.Const.Bool}} case semantics.ValInfinity: - return &pb.Value{Kind: &pb.Value_StringValue{StringValue: "*"}} + return &pb.Value{Kind: &pb.Value_Infinity{Infinity: true}} default: return &pb.Value{Kind: &pb.Value_Null{Null: "unsupported const kind"}} } @@ -446,6 +446,10 @@ var ( // that a feature value holds no value, which is something to read, not to supply. ErrUnsetNotAccepted = errors.New("unset is not a value a caller can supply") + // ErrInfinityNotAsserted reports the infinity arm arriving as false. The arm + // is the unbounded value itself, so false states no value at all. + ErrInfinityNotAsserted = errors.New("the infinity arm states no value unless it is true") + // ErrArrayDimensionNotPositive reports an array sent with a dimension of no // extent, which Collections::Array declares as dimensions: Positive. ErrArrayDimensionNotPositive = errors.New("array dimension is not positive") @@ -488,6 +492,15 @@ func ValueCarriesMeasurementRef(pv *pb.Value) bool { }) } +// ValueCarriesInfinity reports whether a value, or any value nested in it, is +// the unbounded value: the kind infinity_value governs. +func ValueCarriesInfinity(pv *pb.Value) bool { + return valueCarries(pv, func(v *pb.Value) bool { + _, ok := v.GetKind().(*pb.Value_Infinity) + return ok + }) +} + // ValueCarriesComplex reports whether a value, or any value nested in it, is a // Complex: the kind the complex_values capability governs. func ValueCarriesComplex(pv *pb.Value) bool { @@ -570,6 +583,11 @@ func ProtoToValueIn(pv *pb.Value, idx *symbols.Index, sem *semantics.Model) (run return protoToVectorQuantity(k.VectorQuantity, idx, sem) case *pb.Value_MeasurementRef: return ProtoToMeasurementRef(k.MeasurementRef, idx, sem) + case *pb.Value_Infinity: + if !k.Infinity { + return runtime.Value{}, ErrInfinityNotAsserted + } + return protoToScalar(pv), nil default: return protoToScalar(pv), nil } @@ -1141,6 +1159,11 @@ func protoToScalar(pv *pb.Value) runtime.Value { return runtime.Value{Kind: runtime.ValNull} case *pb.Value_Complex: return runtime.NewComplex(ProtoToComplex(k.Complex)) + case *pb.Value_Infinity: + if !k.Infinity { + return runtime.Value{Kind: runtime.ValNull} + } + return runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}} default: return runtime.Value{Kind: runtime.ValNull} } diff --git a/internal/grpc/convert_infinity_test.go b/internal/grpc/convert_infinity_test.go new file mode 100644 index 000000000..15a4c1f2f --- /dev/null +++ b/internal/grpc/convert_infinity_test.go @@ -0,0 +1,169 @@ +package grpc + +import ( + "context" + "errors" + "strings" + "testing" + + "connectrpc.com/connect" + + pb "github.com/Open-MBEE/OpenSysML/api/proto" + "github.com/Open-MBEE/OpenSysML/internal/core/runtime" + "github.com/Open-MBEE/OpenSysML/internal/core/semantics" + "github.com/Open-MBEE/OpenSysML/internal/core/symbols" +) + +// infinityWireModel yields the unbounded value as a feature value, alone and +// nested in a sequence, beside the ordinary string that prints the same way. +const infinityWireModel = ` +package U { + private import ScalarValues::*; + + attribute unbounded = *; + attribute star : String = "*"; + attribute bounds [*] = (1, *); + + action pass { + in x; + out y; + first start; + action inner { assign y := x; } + then done; + succession first start then inner; + } +} +` + +func infinityValue() *pb.Value { + return &pb.Value{Kind: &pb.Value_Infinity{Infinity: true}} +} + +// The unbounded value crosses as its own arm, distinct from the string "*" a +// client would otherwise read as text, and reads back as the same value. +func TestInfinityRoundTrip(t *testing.T) { + idx := symbols.NewIndex() + unbounded := runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}} + + pv := ValueToProto(unbounded, idx) + if _, ok := pv.GetKind().(*pb.Value_Infinity); !ok { + t.Fatalf("* crossed as %T, want the infinity arm", pv.GetKind()) + } + + back, err := ProtoToValueIn(pv, idx, nil) + if err != nil { + t.Fatalf("ProtoToValueIn: %v", err) + } + if back.Kind != runtime.ValConst || !back.Const.IsUnbounded() { + t.Errorf("round trip of * = %s (%v)", back.Kind, back) + } + + // The string "*" stays a string in both directions. + str := ValueToProto(runtime.NewStringValue("*"), idx) + if str.GetStringValue() != "*" { + t.Errorf(`"*" crossed as %T, want a string`, str.GetKind()) + } + strBack, err := ProtoToValueIn(str, idx, nil) + if err != nil { + t.Fatalf(`ProtoToValueIn("*"): %v`, err) + } + if strBack.Kind != runtime.ValString || strBack.Str() != "*" { + t.Errorf(`round trip of "*" = %s (%v)`, strBack.Kind, strBack) + } + + seq := runtime.NewSequence() + seq.Append(runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInt, Int: 1}}) + seq.Append(unbounded) + elements := ValueToProto(runtime.NewSequenceValue(seq), idx).GetSequence().GetElements() + if len(elements) != 2 { + t.Fatalf("(1, *) crossed as %d elements", len(elements)) + } + if _, ok := elements[1].GetKind().(*pb.Value_Infinity); !ok { + t.Errorf("(1, *)#2 crossed as %T, want the infinity arm", elements[1].GetKind()) + } +} + +// Evaluating the model reports the unbounded value on the arm and the ordinary +// string as text, so a client can tell them apart. +func TestInfinityEvaluate(t *testing.T) { + srv := mustNewService(t, 4) + modelHash := mustParse(t, srv, infinityWireModel) + + if pv := mustEvaluate(t, srv, modelHash, "U::unbounded"); !pv.GetInfinity() { + t.Errorf("U::unbounded = %v, want the infinity arm", pv) + } + if pv := mustEvaluate(t, srv, modelHash, "U::star"); pv.GetStringValue() != "*" { + t.Errorf(`U::star = %v, want the string "*"`, pv) + } + bounds := mustEvaluate(t, srv, modelHash, "U::bounds").GetSequence().GetElements() + if len(bounds) != 2 || bounds[0].GetIntValue() != 1 || !bounds[1].GetInfinity() { + t.Errorf("U::bounds = %v, want (1, *)", bounds) + } +} + +// The arm is advertised under its own capability, so a client can require it; a +// service withholding it reports the value as unsupported — nested in a +// structured value included — and refuses one sent to it rather than reading it +// as another value. The string "*" is unaffected. +func TestInfinityCapability(t *testing.T) { + ctx := context.Background() + found := false + for _, c := range Capabilities() { + found = found || c == CapabilityInfinityValue + } + if !found { + t.Errorf("capabilities %v do not include %q", Capabilities(), CapabilityInfinityValue) + } + + withheld := mustNewServiceWithout(t, CapabilityInfinityValue) + modelHash := mustParse(t, withheld, infinityWireModel) + + const want = "unsupported: unbounded value *" + got := mustEvaluate(t, withheld, modelHash, "U::unbounded") + if got.GetInfinity() || got.GetNull() != want { + t.Errorf("U::unbounded without %s = %v, want null %q", CapabilityInfinityValue, got, want) + } + if pv := mustEvaluate(t, withheld, modelHash, "U::star"); pv.GetStringValue() != "*" { + t.Errorf(`U::star without %s = %v, want the string "*"`, CapabilityInfinityValue, pv) + } + bounds := mustEvaluate(t, withheld, modelHash, "U::bounds").GetSequence().GetElements() + if len(bounds) != 2 || bounds[1].GetNull() != want { + t.Errorf("U::bounds without %s = %v, want the element withheld", CapabilityInfinityValue, bounds) + } + + nested := &pb.Value{Kind: &pb.Value_Sequence{Sequence: &pb.ValueSequence{Elements: []*pb.Value{infinityValue()}}}} + for name, input := range map[string]*pb.Value{"unbounded": infinityValue(), "nested": nested} { + _, err := withheld.ExecuteAction(ctx, &pb.ExecuteActionRequest{ + ModelHash: modelHash, + ActionSymbolId: "U::pass", + Inputs: map[string]*pb.Value{"x": input}, + }) + if connect.CodeOf(err) != connect.CodeUnimplemented || !strings.Contains(err.Error(), CapabilityInfinityValue) { + t.Errorf("ExecuteAction with %s input without %s: err = %v, want UNIMPLEMENTED naming the capability", name, CapabilityInfinityValue, err) + } + } +} + +// TestProtoToValueRefusesAFalseInfinityArm refuses the infinity arm sent as +// false, directly and nested: the arm is the unbounded value itself, so false +// states no value and must not be read as one. +func TestProtoToValueRefusesAFalseInfinityArm(t *testing.T) { + false_ := &pb.Value{Kind: &pb.Value_Infinity{Infinity: false}} + for _, tc := range []struct { + name string + sent *pb.Value + }{ + {"directly", false_}, + {"in a sequence", &pb.Value{Kind: &pb.Value_Sequence{Sequence: &pb.ValueSequence{Elements: []*pb.Value{false_}}}}}, + {"in an array", &pb.Value{Kind: &pb.Value_Array{Array: &pb.Array{Dimensions: []int64{1}, Elements: []*pb.Value{false_}}}}}, + } { + t.Run(tc.name, func(t *testing.T) { + if _, err := ProtoToValueIn(tc.sent, nil, nil); !errors.Is(err, ErrInfinityNotAsserted) { + t.Errorf("error %v, want the infinity arm refused", err) + } + }) + } + if got, err := ProtoToValueIn(infinityValue(), nil, nil); err != nil || !got.Const.IsUnbounded() { + t.Errorf("infinity: true read as %v (%v), want the unbounded value", got.Kind, err) + } +} diff --git a/internal/grpc/service.go b/internal/grpc/service.go index 699005caf..10c6bc9be 100644 --- a/internal/grpc/service.go +++ b/internal/grpc/service.go @@ -109,6 +109,10 @@ const CapabilityMeasurementRefs = "measurement_refs" // verification case through RunAnalysis. const CapabilityVerificationVerdicts = "verification_verdicts" +// CapabilityInfinityValue names the capability of carrying the unbounded value +// `*` as Value.infinity, rather than reporting it as an unsupported null. +const CapabilityInfinityValue = "infinity_value" + // capabilities is what this build supports, in report order. A capability is // only ever added: renaming or dropping one breaks clients that require it. var capabilities = []string{ @@ -119,6 +123,7 @@ var capabilities = []string{ CapabilityStrictConformance, CapabilityDocumentQuery, CapabilityRenderDocument, CapabilityParseSources, CapabilityComplexValues, CapabilityStructuredValues, CapabilityMeasurementRefs, CapabilityVerificationVerdicts, + CapabilityInfinityValue, } type capabilityAvailability struct { @@ -269,7 +274,12 @@ func (s *Service) requireValueCapabilities(pv *pb.Value) error { } } if ValueCarriesMeasurementRef(pv) { - return s.requireCapability(CapabilityMeasurementRefs) + if err := s.requireCapability(CapabilityMeasurementRefs); err != nil { + return err + } + } + if ValueCarriesInfinity(pv) { + return s.requireCapability(CapabilityInfinityValue) } return nil } diff --git a/internal/repl/docquery.go b/internal/repl/docquery.go index 858d99f63..1d6244408 100644 --- a/internal/repl/docquery.go +++ b/internal/repl/docquery.go @@ -376,7 +376,7 @@ func formatQueryValue(value queryexec.Value) string { return strconv.FormatBool(boolean) } if value.Kind() == queryexec.ValueInfinity { - return "∞" + return "*" } if quantity, ok := value.Quantity(); ok { return quantity.String() diff --git a/internal/repl/metadata_about_eval_test.go b/internal/repl/metadata_about_eval_test.go new file mode 100644 index 000000000..14826e84d --- /dev/null +++ b/internal/repl/metadata_about_eval_test.go @@ -0,0 +1,42 @@ +package repl + +import ( + "strings" + "testing" +) + +// aboutAnnotatedModel annotates one part inline and from an `about` usage in +// another package, and annotates the package itself. +const aboutAnnotatedModel = `package Probe { + private import ScalarValues::*; + metadata def Safety { attribute level : Integer = 2; } + metadata def Legacy; + part def Vehicle; + part seatBelt : Vehicle { + @Safety { level = 3; } + @Legacy; + } +} +package About { + metadata Probe::Safety about Probe::seatBelt { level = 9; } + metadata Probe::Legacy about Probe; +}` + +// TestEvalMetadataReadsAboutAnnotations requires `.metadata` at the prompt to +// answer the `about`-form annotations too: the prompt evaluates against its own +// scope tree, so reaching them cannot depend on holding the indexed symbol. +func TestEvalMetadataReadsAboutAnnotations(t *testing.T) { + s := NewSession() + submitModel(t, s, aboutAnnotatedModel) + + got := metaOK(t, s, "%eval Probe::seatBelt.metadata") + if n := strings.Count(got, "Instance("); n != 3 { + t.Errorf("seatBelt.metadata = %q, want the two inline annotations and the `about` one", got) + } + if got := metaOK(t, s, "%eval Probe::seatBelt.metadata#(3).level"); !strings.Contains(got, "9") { + t.Errorf("the `about` annotation's level = %q, want the bound 9", got) + } + if got := metaOK(t, s, "%eval Probe.metadata"); strings.Count(got, "Instance(") != 1 { + t.Errorf("Probe.metadata = %q, want the annotation about the package", got) + } +} diff --git a/internal/repl/runtime_commands_test.go b/internal/repl/runtime_commands_test.go index 1e91841f8..bfef4f846 100644 --- a/internal/repl/runtime_commands_test.go +++ b/internal/repl/runtime_commands_test.go @@ -367,7 +367,7 @@ func TestFormatValue(t *testing.T) { {"int", runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInt, Int: 7}}, "7"}, {"real", runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValReal, Real: 1.5}}, "1.5"}, {"bool", runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValBool, Bool: true}}, "true"}, - {"infinity", runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}}, "∞"}, + {"infinity", runtime.Value{Kind: runtime.ValConst, Const: semantics.Value{Kind: semantics.ValInfinity}}, "*"}, {"null", runtime.Value{Kind: runtime.ValNull}, "null"}, {"string", runtime.NewStringValue("hi"), `"hi"`}, {"instance", runtime.Value{Kind: runtime.ValInstance, Instance: 3}, "Instance(ID: 3)"},