@primmel/primmel 1.21.18 → 1.21.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -676,6 +676,10 @@ function parseSeriesDecl(block) {
676
676
  let i = 0;
677
677
  while (i < t.length) {
678
678
  const cmd = t[i++];
679
+ if (cmd === "record") {
680
+ decl.record = stripWrapping(t[i++]);
681
+ continue;
682
+ }
679
683
  if (cmd !== "axis" && cmd !== "cell") {
680
684
  if (i < t.length) {
681
685
  unwrapBlock(t[i - 1]);
@@ -753,7 +757,11 @@ function dumpSeriesDecl(decl) {
753
757
  if (decl.cellUnit) {
754
758
  out += 'unit "' + escapeString(decl.cellUnit) + '" ';
755
759
  }
756
- out += "} }";
760
+ out += "} ";
761
+ if (decl.record !== void 0) {
762
+ out += "record " + decl.record + " ";
763
+ }
764
+ out += "}";
757
765
  return out;
758
766
  }
759
767
 
@@ -2945,15 +2953,30 @@ function readQuantityBlock(content) {
2945
2953
  break;
2946
2954
  }
2947
2955
  if (cmd === "value") {
2948
- out.value = coerceValueToken(t[i++]);
2956
+ const rawTok = t[i++];
2957
+ out.value = coerceValueToken(rawTok);
2958
+ const bare = stripWrapping(rawTok);
2959
+ if (typeof out.value === "number" && String(out.value) !== bare) {
2960
+ out.valueLiteral = bare;
2961
+ }
2949
2962
  } else if (cmd === "unit") {
2950
2963
  out.unit = stripWrapping(t[i++]);
2951
2964
  } else if (cmd === "kind" || cmd === "quantity_kind") {
2952
2965
  out.quantityKind = stripWrapping(t[i++]);
2953
2966
  } else if (cmd === "uncertainty") {
2954
- out.uncertainty = coerceValueToken(t[i++]);
2967
+ const rawTok = t[i++];
2968
+ out.uncertainty = coerceValueToken(rawTok);
2969
+ const bare = stripWrapping(rawTok);
2970
+ if (typeof out.uncertainty === "number" && String(out.uncertainty) !== bare) {
2971
+ out.uncertaintyLiteral = bare;
2972
+ }
2955
2973
  } else if (cmd === "tolerance") {
2956
- out.tolerance = coerceValueToken(t[i++]);
2974
+ const rawTok = t[i++];
2975
+ out.tolerance = coerceValueToken(rawTok);
2976
+ const bare = stripWrapping(rawTok);
2977
+ if (typeof out.tolerance === "number" && String(out.tolerance) !== bare) {
2978
+ out.toleranceLiteral = bare;
2979
+ }
2957
2980
  } else if (cmd === "provenance") {
2958
2981
  out.provenance = readProvenanceBlock(unwrapBlock(t[i++]));
2959
2982
  } else {
@@ -3025,13 +3048,15 @@ function dumpScalarToken(v) {
3025
3048
  }
3026
3049
  function dumpQuantityValue(v) {
3027
3050
  if (!needsQuantityBlock(v)) {
3028
- const val = dumpScalarToken(v.value);
3051
+ const val = v.valueLiteral ?? dumpScalarToken(v.value);
3029
3052
  return v.unit === void 0 ? val : val + " " + dumpBareSafe(v.unit);
3030
3053
  }
3031
3054
  return dumpQuantityBlock(v);
3032
3055
  }
3033
3056
  function dumpQuantityBlock(v) {
3034
- const parts = ["value " + dumpScalarToken(v.value)];
3057
+ const parts = [
3058
+ "value " + (v.valueLiteral ?? dumpScalarToken(v.value))
3059
+ ];
3035
3060
  if (v.unit !== void 0) {
3036
3061
  parts.push('unit "' + escapeString(v.unit) + '"');
3037
3062
  }
@@ -3039,10 +3064,14 @@ function dumpQuantityBlock(v) {
3039
3064
  parts.push("kind " + dumpBareSafe(v.quantityKind));
3040
3065
  }
3041
3066
  if (v.uncertainty !== void 0) {
3042
- parts.push("uncertainty " + dumpScalarToken(v.uncertainty));
3067
+ parts.push(
3068
+ "uncertainty " + (v.uncertaintyLiteral ?? dumpScalarToken(v.uncertainty))
3069
+ );
3043
3070
  }
3044
3071
  if (v.tolerance !== void 0) {
3045
- parts.push("tolerance " + dumpScalarToken(v.tolerance));
3072
+ parts.push(
3073
+ "tolerance " + (v.toleranceLiteral ?? dumpScalarToken(v.tolerance))
3074
+ );
3046
3075
  }
3047
3076
  if (v.provenance !== void 0) {
3048
3077
  parts.push("provenance " + dumpProvenanceBlock(v.provenance));
@@ -3107,6 +3136,9 @@ function parseParamList(block, allowInitial = false) {
3107
3136
  const [rawValue, rawUnit] = parts;
3108
3137
  const value = coerceValueToken(rawValue);
3109
3138
  const initial = rawUnit === void 0 ? { value } : { value, unit: stripWrapping(rawUnit) };
3139
+ if (typeof value === "number" && String(value) !== stripWrapping(rawValue)) {
3140
+ initial.valueLiteral = stripWrapping(rawValue);
3141
+ }
3110
3142
  param.initial = initial;
3111
3143
  }
3112
3144
  }
@@ -15320,7 +15352,8 @@ var conditionSetConstruct = {
15320
15352
  field: "conditionSets",
15321
15353
  takesID: true,
15322
15354
  parse: parseConditionSet,
15323
- dump: dumpConditionSet
15355
+ dump: dumpConditionSet,
15356
+ deprecated: "the severity/condition register is the legacy spelling \u2014 migrate to the typed table construct (typed columns, typed rows; the values that decide testing bind in limits via table:<id>.<column>); the legacy spelling keeps parsing as visible debt"
15324
15357
  };
15325
15358
  var subjectConstruct = {
15326
15359
  keyword: "subject",
@@ -23607,6 +23640,14 @@ var CHECK_RULES = [
23607
23640
  "normal",
23608
23641
  "the run store registry and the record forms of the test agree on the data class \u2014 the output records and the store hold the same shape"
23609
23642
  ),
23643
+ R(
23644
+ "C182",
23645
+ "series-record-fields",
23646
+ "quantities",
23647
+ "error",
23648
+ "normal",
23649
+ "a series variable whose series declares a record form types its row members by that form\u2019s typed fields \u2014 a collection derivation\u2019s lambda members resolve against them, never kind-silent"
23650
+ ),
23610
23651
  R(
23611
23652
  "C173",
23612
23653
  "step-plane-refs-resolve",
@@ -29745,6 +29786,71 @@ function checkPackage(dir, options = {}) {
29745
29786
  }
29746
29787
  }
29747
29788
  }
29789
+ {
29790
+ const recordFormFields = /* @__PURE__ */ new Map();
29791
+ for (const f of standard.forms ?? []) {
29792
+ recordFormFields.set(f.id, new Set((f.fields ?? []).map((x) => x.name)));
29793
+ }
29794
+ const walkMembers = (n, bound, out) => {
29795
+ if (n.type === "nav") {
29796
+ const inner = new Map(bound);
29797
+ inner.set(n.var, n.source);
29798
+ walkMembers(n.body, inner, out);
29799
+ return;
29800
+ }
29801
+ if (n.type === "name" && n.path.length > 0) {
29802
+ const parts = [...n.path[0].split("."), ...n.path.slice(1)];
29803
+ if (parts.length > 1) {
29804
+ const src = bound.get(parts[0]);
29805
+ if (src !== void 0) {
29806
+ out.push({ source: src, field: parts.slice(1).join(".") });
29807
+ }
29808
+ }
29809
+ return;
29810
+ }
29811
+ const kids = n.type === "call" ? n.args : n.type === "binop" ? [n.left, n.right] : n.type === "unop" ? [n.operand] : n.type === "ifelse" ? [n.cond, n.then, n.else] : [];
29812
+ for (const k of kids) {
29813
+ walkMembers(k, bound, out);
29814
+ }
29815
+ };
29816
+ for (const t of standard.conformanceTests ?? []) {
29817
+ for (const v of t.variables ?? []) {
29818
+ const rec = v.series?.record;
29819
+ if (!rec) {
29820
+ continue;
29821
+ }
29822
+ const fields = recordFormFields.get(rec);
29823
+ if (!fields) {
29824
+ err(
29825
+ "C182",
29826
+ `conformance test ${t.id}: variable "${v.name}" series record "${rec}" names no declared form \u2014 the row members type by the record form's fields (series-record-fields)`
29827
+ );
29828
+ continue;
29829
+ }
29830
+ if (!v.derivation) {
29831
+ continue;
29832
+ }
29833
+ let ast;
29834
+ try {
29835
+ ast = parseExpression(
29836
+ v.derivation.replace(/^ocl\{/, "").replace(/\}$/, "")
29837
+ );
29838
+ } catch {
29839
+ continue;
29840
+ }
29841
+ const members = [];
29842
+ walkMembers(ast, /* @__PURE__ */ new Map(), members);
29843
+ for (const m of members) {
29844
+ if (m.source === v.name && !fields.has(m.field)) {
29845
+ err(
29846
+ "C182",
29847
+ `conformance test ${t.id}: variable "${v.name}" derivation names "m.${m.field}" \u2014 the record form ${rec} declares no such field; the row members are its typed fields (series-record-fields)`
29848
+ );
29849
+ }
29850
+ }
29851
+ }
29852
+ }
29853
+ }
29748
29854
  {
29749
29855
  const KNOWN_CONTENT = new Set(PASSPORT_CONTENT_CLASSES);
29750
29856
  const KNOWN_LEVELS = new Set(PASSPORT_UPI_LEVELS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primmel/primmel",
3
- "version": "1.21.18",
3
+ "version": "1.21.19",
4
4
  "description": "Primmel — parser, types, and serializer for the Primmel modelling language (successor to MMEL)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",