wadi-mcp 0.1.11 → 0.1.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.
Files changed (2) hide show
  1. package/dist/server.mjs +1552 -570
  2. package/package.json +5 -4
package/dist/server.mjs CHANGED
@@ -14242,7 +14242,7 @@ function setDimensionUnits(u) {
14242
14242
  function metersToUnits2(meters) {
14243
14243
  const { system, perUnit } = activeUnits;
14244
14244
  const unitsPerFoot2 = perUnit / (FEET_PER_DISPLAY_UNIT2[system] ?? 1);
14245
- return meters * unitsPerFoot2 * FEET_PER_METER2;
14245
+ return meters * unitsPerFoot2 * FEET_PER_METER3;
14246
14246
  }
14247
14247
  function formatDimension(length) {
14248
14248
  const { system, perUnit, precision } = activeUnits;
@@ -14268,7 +14268,7 @@ function fFloat(n2) {
14268
14268
  if (Number.isInteger(n2)) return `${n2}.0`;
14269
14269
  return String(n2);
14270
14270
  }
14271
- var DEFAULT_UNITS, activeUnits, FEET_PER_DISPLAY_UNIT2, FEET_PER_METER2, SUFFIX;
14271
+ var DEFAULT_UNITS, activeUnits, FEET_PER_DISPLAY_UNIT2, FEET_PER_METER3, SUFFIX;
14272
14272
  var init_format = __esm({
14273
14273
  "../editor/src/svg2d/format.ts"() {
14274
14274
  init_config();
@@ -14285,7 +14285,7 @@ var init_format = __esm({
14285
14285
  centimeters: 0.032808399,
14286
14286
  millimeters: 3280839e-9
14287
14287
  };
14288
- FEET_PER_METER2 = 3.280839895;
14288
+ FEET_PER_METER3 = 3.280839895;
14289
14289
  SUFFIX = {
14290
14290
  feet: "'",
14291
14291
  meters: " m",
@@ -47141,13 +47141,13 @@ var require_react_dom_client_development = __commonJS({
47141
47141
  "React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue."
47142
47142
  );
47143
47143
  child._store.validated = 1;
47144
- var componentName2 = getComponentNameFromFiber(returnFiber), componentKey = componentName2 || "null";
47145
- if (!ownerHasKeyUseWarning[componentKey]) {
47146
- ownerHasKeyUseWarning[componentKey] = true;
47144
+ var componentName2 = getComponentNameFromFiber(returnFiber), componentKey2 = componentName2 || "null";
47145
+ if (!ownerHasKeyUseWarning[componentKey2]) {
47146
+ ownerHasKeyUseWarning[componentKey2] = true;
47147
47147
  child = child._owner;
47148
47148
  returnFiber = returnFiber._debugOwner;
47149
47149
  var currentComponentErrorInfo = "";
47150
- returnFiber && "number" === typeof returnFiber.tag && (componentKey = getComponentNameFromFiber(returnFiber)) && (currentComponentErrorInfo = "\n\nCheck the render method of `" + componentKey + "`.");
47150
+ returnFiber && "number" === typeof returnFiber.tag && (componentKey2 = getComponentNameFromFiber(returnFiber)) && (currentComponentErrorInfo = "\n\nCheck the render method of `" + componentKey2 + "`.");
47151
47151
  currentComponentErrorInfo || componentName2 && (currentComponentErrorInfo = "\n\nCheck the top-level render call using <" + componentName2 + ">.");
47152
47152
  var childOwnerAppendix = "";
47153
47153
  null != child && returnFiber !== child && (componentName2 = null, "number" === typeof child.tag ? componentName2 = getComponentNameFromFiber(child) : "string" === typeof child.name && (componentName2 = child.name), componentName2 && (childOwnerAppendix = " It was passed a child from " + componentName2 + "."));
@@ -369777,6 +369777,21 @@ var Reduction;
369777
369777
  })(Reduction || (Reduction = {}));
369778
369778
 
369779
369779
  // ../wadi-dsl/node_modules/langium/lib/utils/ast-utils.js
369780
+ var ast_utils_exports = {};
369781
+ __export(ast_utils_exports, {
369782
+ assignMandatoryProperties: () => assignMandatoryProperties,
369783
+ copyAstNode: () => copyAstNode,
369784
+ findRootNode: () => findRootNode,
369785
+ getContainerOfType: () => getContainerOfType,
369786
+ getDocument: () => getDocument,
369787
+ getReferenceNodes: () => getReferenceNodes,
369788
+ hasContainerOfType: () => hasContainerOfType,
369789
+ linkContentToContainer: () => linkContentToContainer,
369790
+ streamAllContents: () => streamAllContents,
369791
+ streamAst: () => streamAst,
369792
+ streamContents: () => streamContents,
369793
+ streamReferences: () => streamReferences
369794
+ });
369780
369795
  function linkContentToContainer(node, options = {}) {
369781
369796
  for (const [name, value] of Object.entries(node)) {
369782
369797
  if (!name.startsWith("$")) {
@@ -369811,6 +369826,16 @@ function getContainerOfType(node, typePredicate) {
369811
369826
  }
369812
369827
  return void 0;
369813
369828
  }
369829
+ function hasContainerOfType(node, predicate) {
369830
+ let item2 = node;
369831
+ while (item2) {
369832
+ if (predicate(item2)) {
369833
+ return true;
369834
+ }
369835
+ item2 = item2.$container;
369836
+ }
369837
+ return false;
369838
+ }
369814
369839
  function getDocument(node) {
369815
369840
  const rootNode = findRootNode(node);
369816
369841
  const result = rootNode.$document;
@@ -369937,6 +369962,38 @@ function copyDefaultValue(propertyType) {
369937
369962
  return propertyType;
369938
369963
  }
369939
369964
  }
369965
+ function copyAstNode(node, buildReference, trace) {
369966
+ const copy = { $type: node.$type };
369967
+ if (trace) {
369968
+ trace.set(node, copy);
369969
+ trace.set(copy, node);
369970
+ }
369971
+ for (const [name, value] of Object.entries(node)) {
369972
+ if (!name.startsWith("$")) {
369973
+ if (isAstNode(value)) {
369974
+ copy[name] = copyAstNode(value, buildReference, trace);
369975
+ } else if (isReference(value)) {
369976
+ copy[name] = buildReference(copy, name, value.$refNode, value.$refText, value);
369977
+ } else if (Array.isArray(value)) {
369978
+ const copiedArray = [];
369979
+ for (const element of value) {
369980
+ if (isAstNode(element)) {
369981
+ copiedArray.push(copyAstNode(element, buildReference, trace));
369982
+ } else if (isReference(element)) {
369983
+ copiedArray.push(buildReference(copy, name, element.$refNode, element.$refText, element));
369984
+ } else {
369985
+ copiedArray.push(element);
369986
+ }
369987
+ }
369988
+ copy[name] = copiedArray;
369989
+ } else {
369990
+ copy[name] = value;
369991
+ }
369992
+ }
369993
+ }
369994
+ linkContentToContainer(copy, { deep: true });
369995
+ return copy;
369996
+ }
369940
369997
 
369941
369998
  // ../wadi-dsl/node_modules/langium/lib/languages/generated/ast.js
369942
369999
  var AbstractElement = {
@@ -384245,6 +384302,46 @@ var StreamScope = class {
384245
384302
  }
384246
384303
  }
384247
384304
  };
384305
+ var MapScope = class {
384306
+ constructor(elements, outerScope, options) {
384307
+ this.elements = /* @__PURE__ */ new Map();
384308
+ this.caseInsensitive = options?.caseInsensitive ?? false;
384309
+ this.concatOuterScope = options?.concatOuterScope ?? true;
384310
+ for (const element of elements) {
384311
+ const name = this.caseInsensitive ? element.name.toLowerCase() : element.name;
384312
+ this.elements.set(name, element);
384313
+ }
384314
+ this.outerScope = outerScope;
384315
+ }
384316
+ getElement(name) {
384317
+ const localName = this.caseInsensitive ? name.toLowerCase() : name;
384318
+ const local = this.elements.get(localName);
384319
+ if (local) {
384320
+ return local;
384321
+ }
384322
+ if (this.outerScope) {
384323
+ return this.outerScope.getElement(name);
384324
+ }
384325
+ return void 0;
384326
+ }
384327
+ getElements(name) {
384328
+ const localName = this.caseInsensitive ? name.toLowerCase() : name;
384329
+ const local = this.elements.get(localName);
384330
+ const arr = local ? [local] : [];
384331
+ if ((this.concatOuterScope || arr.length > 0) && this.outerScope) {
384332
+ return stream(arr).concat(this.outerScope.getElements(name));
384333
+ } else {
384334
+ return stream(arr);
384335
+ }
384336
+ }
384337
+ getAllElements() {
384338
+ let elementStream = stream(this.elements.values());
384339
+ if (this.outerScope) {
384340
+ elementStream = elementStream.concat(this.outerScope.getAllElements());
384341
+ }
384342
+ return elementStream;
384343
+ }
384344
+ };
384248
384345
  var MultiMapScope = class {
384249
384346
  constructor(elements, outerScope, options) {
384250
384347
  this.elements = new MultiMap();
@@ -387127,11 +387224,6 @@ var AssetDecl = {
387127
387224
  id: "id",
387128
387225
  src: "src"
387129
387226
  };
387130
- var AssetRef = {
387131
- $type: "AssetRef",
387132
- id: "id",
387133
- ns: "ns"
387134
- };
387135
387227
  var Beam = {
387136
387228
  $type: "Beam",
387137
387229
  enabled: "enabled",
@@ -387167,8 +387259,8 @@ var Component = {
387167
387259
  enabled: "enabled",
387168
387260
  layer: "layer",
387169
387261
  name: "name",
387170
- ns: "ns",
387171
- ref: "ref",
387262
+ rotation: "rotation",
387263
+ target: "target",
387172
387264
  x: "x",
387173
387265
  y: "y",
387174
387266
  z_offset: "z_offset"
@@ -387193,12 +387285,23 @@ var ComponentParam = {
387193
387285
  label: "label",
387194
387286
  name: "name"
387195
387287
  };
387288
+ var ConfigGroup = {
387289
+ $type: "ConfigGroup",
387290
+ description: "description",
387291
+ inputs: "inputs",
387292
+ label: "label"
387293
+ };
387196
387294
  var ConfigInput = {
387197
387295
  $type: "ConfigInput"
387198
387296
  };
387297
+ var ConfigItem = {
387298
+ $type: "ConfigItem"
387299
+ };
387199
387300
  var Configurator = {
387200
387301
  $type: "Configurator",
387201
- inputs: "inputs"
387302
+ description: "description",
387303
+ items: "items",
387304
+ title: "title"
387202
387305
  };
387203
387306
  var Defaults = {
387204
387307
  $type: "Defaults",
@@ -387212,6 +387315,7 @@ var Expr = {
387212
387315
  };
387213
387316
  var Floor = {
387214
387317
  $type: "Floor",
387318
+ enabled: "enabled",
387215
387319
  height: "height",
387216
387320
  name: "name",
387217
387321
  number: "number",
@@ -387385,12 +387489,14 @@ function isNum(item2) {
387385
387489
  }
387386
387490
  var NumberInput = {
387387
387491
  $type: "NumberInput",
387492
+ description: "description",
387388
387493
  label: "label",
387389
387494
  target: "target",
387390
387495
  unit: "unit"
387391
387496
  };
387392
387497
  var Opening = {
387393
387498
  $type: "Opening",
387499
+ direction: "direction",
387394
387500
  height: "height",
387395
387501
  kind: "kind",
387396
387502
  name: "name",
@@ -387404,9 +387510,11 @@ var Pillar = {
387404
387510
  enabled: "enabled",
387405
387511
  height: "height",
387406
387512
  l: "l",
387513
+ l_auto: "l_auto",
387407
387514
  layer: "layer",
387408
387515
  name: "name",
387409
387516
  w: "w",
387517
+ w_auto: "w_auto",
387410
387518
  x: "x",
387411
387519
  y: "y",
387412
387520
  z_offset: "z_offset"
@@ -387451,6 +387559,7 @@ var Roof = {
387451
387559
  $type: "Roof",
387452
387560
  default_endpoint: "default_endpoint",
387453
387561
  enabled: "enabled",
387562
+ framing: "framing",
387454
387563
  gable_wall_thickness: "gable_wall_thickness",
387455
387564
  layer: "layer",
387456
387565
  material: "material",
@@ -387529,6 +387638,7 @@ var Segment = {
387529
387638
  };
387530
387639
  var SelectInput = {
387531
387640
  $type: "SelectInput",
387641
+ description: "description",
387532
387642
  label: "label",
387533
387643
  options: "options",
387534
387644
  target: "target"
@@ -387547,6 +387657,7 @@ var Site = {
387547
387657
  };
387548
387658
  var SliderInput = {
387549
387659
  $type: "SliderInput",
387660
+ description: "description",
387550
387661
  label: "label",
387551
387662
  max: "max",
387552
387663
  min: "min",
@@ -387556,8 +387667,10 @@ var SliderInput = {
387556
387667
  };
387557
387668
  var Slope = {
387558
387669
  $type: "Slope",
387559
- by: "by",
387560
- value: "value"
387670
+ angle_deg: "angle_deg",
387671
+ angle_left: "angle_left",
387672
+ angle_right: "angle_right",
387673
+ ridge_h: "ridge_h"
387561
387674
  };
387562
387675
  var Staircase = {
387563
387676
  $type: "Staircase",
@@ -387581,6 +387694,7 @@ var Staircase = {
387581
387694
  };
387582
387695
  var ToggleInput = {
387583
387696
  $type: "ToggleInput",
387697
+ description: "description",
387584
387698
  label: "label",
387585
387699
  target: "target"
387586
387700
  };
@@ -387676,19 +387790,6 @@ var WadiAstReflection = class extends AbstractAstReflection {
387676
387790
  },
387677
387791
  superTypes: []
387678
387792
  },
387679
- AssetRef: {
387680
- name: AssetRef.$type,
387681
- properties: {
387682
- id: {
387683
- name: AssetRef.id
387684
- },
387685
- ns: {
387686
- name: AssetRef.ns,
387687
- optional: true
387688
- }
387689
- },
387690
- superTypes: []
387691
- },
387692
387793
  Beam: {
387693
387794
  name: Beam.$type,
387694
387795
  properties: {
@@ -387776,12 +387877,13 @@ var WadiAstReflection = class extends AbstractAstReflection {
387776
387877
  name: Component.name,
387777
387878
  optional: true
387778
387879
  },
387779
- ns: {
387780
- name: Component.ns,
387880
+ rotation: {
387881
+ name: Component.rotation,
387781
387882
  optional: true
387782
387883
  },
387783
- ref: {
387784
- name: Component.ref
387884
+ target: {
387885
+ name: Component.target,
387886
+ referenceType: ComponentDef.$type
387785
387887
  },
387786
387888
  x: {
387787
387889
  name: Component.x
@@ -387858,17 +387960,47 @@ var WadiAstReflection = class extends AbstractAstReflection {
387858
387960
  },
387859
387961
  superTypes: []
387860
387962
  },
387963
+ ConfigGroup: {
387964
+ name: ConfigGroup.$type,
387965
+ properties: {
387966
+ description: {
387967
+ name: ConfigGroup.description,
387968
+ optional: true
387969
+ },
387970
+ inputs: {
387971
+ name: ConfigGroup.inputs,
387972
+ defaultValue: []
387973
+ },
387974
+ label: {
387975
+ name: ConfigGroup.label
387976
+ }
387977
+ },
387978
+ superTypes: [ConfigItem.$type]
387979
+ },
387861
387980
  ConfigInput: {
387862
387981
  name: ConfigInput.$type,
387863
387982
  properties: {},
387983
+ superTypes: [ConfigItem.$type]
387984
+ },
387985
+ ConfigItem: {
387986
+ name: ConfigItem.$type,
387987
+ properties: {},
387864
387988
  superTypes: []
387865
387989
  },
387866
387990
  Configurator: {
387867
387991
  name: Configurator.$type,
387868
387992
  properties: {
387869
- inputs: {
387870
- name: Configurator.inputs,
387993
+ description: {
387994
+ name: Configurator.description,
387995
+ optional: true
387996
+ },
387997
+ items: {
387998
+ name: Configurator.items,
387871
387999
  defaultValue: []
388000
+ },
388001
+ title: {
388002
+ name: Configurator.title,
388003
+ optional: true
387872
388004
  }
387873
388005
  },
387874
388006
  superTypes: []
@@ -387903,6 +388035,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
387903
388035
  Floor: {
387904
388036
  name: Floor.$type,
387905
388037
  properties: {
388038
+ enabled: {
388039
+ name: Floor.enabled,
388040
+ optional: true
388041
+ },
387906
388042
  height: {
387907
388043
  name: Floor.height,
387908
388044
  optional: true
@@ -388081,6 +388217,7 @@ var WadiAstReflection = class extends AbstractAstReflection {
388081
388217
  },
388082
388218
  assetRef: {
388083
388219
  name: Item.assetRef,
388220
+ referenceType: AssetDecl.$type,
388084
388221
  optional: true
388085
388222
  },
388086
388223
  enabled: {
@@ -388355,6 +388492,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388355
388492
  NumberInput: {
388356
388493
  name: NumberInput.$type,
388357
388494
  properties: {
388495
+ description: {
388496
+ name: NumberInput.description,
388497
+ optional: true
388498
+ },
388358
388499
  label: {
388359
388500
  name: NumberInput.label
388360
388501
  },
@@ -388371,6 +388512,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388371
388512
  Opening: {
388372
388513
  name: Opening.$type,
388373
388514
  properties: {
388515
+ direction: {
388516
+ name: Opening.direction,
388517
+ optional: true
388518
+ },
388374
388519
  height: {
388375
388520
  name: Opening.height
388376
388521
  },
@@ -388410,7 +388555,13 @@ var WadiAstReflection = class extends AbstractAstReflection {
388410
388555
  optional: true
388411
388556
  },
388412
388557
  l: {
388413
- name: Pillar.l
388558
+ name: Pillar.l,
388559
+ optional: true
388560
+ },
388561
+ l_auto: {
388562
+ name: Pillar.l_auto,
388563
+ defaultValue: false,
388564
+ optional: true
388414
388565
  },
388415
388566
  layer: {
388416
388567
  name: Pillar.layer,
@@ -388420,7 +388571,13 @@ var WadiAstReflection = class extends AbstractAstReflection {
388420
388571
  name: Pillar.name
388421
388572
  },
388422
388573
  w: {
388423
- name: Pillar.w
388574
+ name: Pillar.w,
388575
+ optional: true
388576
+ },
388577
+ w_auto: {
388578
+ name: Pillar.w_auto,
388579
+ defaultValue: false,
388580
+ optional: true
388424
388581
  },
388425
388582
  x: {
388426
388583
  name: Pillar.x
@@ -388536,6 +388693,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388536
388693
  name: Roof.enabled,
388537
388694
  optional: true
388538
388695
  },
388696
+ framing: {
388697
+ name: Roof.framing,
388698
+ optional: true
388699
+ },
388539
388700
  gable_wall_thickness: {
388540
388701
  name: Roof.gable_wall_thickness,
388541
388702
  optional: true
@@ -388656,6 +388817,7 @@ var WadiAstReflection = class extends AbstractAstReflection {
388656
388817
  },
388657
388818
  assetRef: {
388658
388819
  name: RoomItem.assetRef,
388820
+ referenceType: AssetDecl.$type,
388659
388821
  optional: true
388660
388822
  },
388661
388823
  enabled: {
@@ -388811,6 +388973,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388811
388973
  SelectInput: {
388812
388974
  name: SelectInput.$type,
388813
388975
  properties: {
388976
+ description: {
388977
+ name: SelectInput.description,
388978
+ optional: true
388979
+ },
388814
388980
  label: {
388815
388981
  name: SelectInput.label
388816
388982
  },
@@ -388859,6 +389025,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388859
389025
  SliderInput: {
388860
389026
  name: SliderInput.$type,
388861
389027
  properties: {
389028
+ description: {
389029
+ name: SliderInput.description,
389030
+ optional: true
389031
+ },
388862
389032
  label: {
388863
389033
  name: SliderInput.label
388864
389034
  },
@@ -388885,11 +389055,21 @@ var WadiAstReflection = class extends AbstractAstReflection {
388885
389055
  Slope: {
388886
389056
  name: Slope.$type,
388887
389057
  properties: {
388888
- by: {
388889
- name: Slope.by
389058
+ angle_deg: {
389059
+ name: Slope.angle_deg,
389060
+ optional: true
388890
389061
  },
388891
- value: {
388892
- name: Slope.value
389062
+ angle_left: {
389063
+ name: Slope.angle_left,
389064
+ optional: true
389065
+ },
389066
+ angle_right: {
389067
+ name: Slope.angle_right,
389068
+ optional: true
389069
+ },
389070
+ ridge_h: {
389071
+ name: Slope.ridge_h,
389072
+ optional: true
388893
389073
  }
388894
389074
  },
388895
389075
  superTypes: []
@@ -388965,6 +389145,10 @@ var WadiAstReflection = class extends AbstractAstReflection {
388965
389145
  ToggleInput: {
388966
389146
  name: ToggleInput.$type,
388967
389147
  properties: {
389148
+ description: {
389149
+ name: ToggleInput.description,
389150
+ optional: true
389151
+ },
388968
389152
  label: {
388969
389153
  name: ToggleInput.label
388970
389154
  },
@@ -389169,7 +389353,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389169
389353
  "terminal": {
389170
389354
  "$type": "RuleCall",
389171
389355
  "rule": {
389172
- "$ref": "#/rules@26"
389356
+ "$ref": "#/rules@29"
389173
389357
  },
389174
389358
  "arguments": []
389175
389359
  }
@@ -389181,7 +389365,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389181
389365
  "terminal": {
389182
389366
  "$type": "RuleCall",
389183
389367
  "rule": {
389184
- "$ref": "#/rules@27"
389368
+ "$ref": "#/rules@30"
389185
389369
  },
389186
389370
  "arguments": []
389187
389371
  }
@@ -389203,7 +389387,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389203
389387
  "terminal": {
389204
389388
  "$type": "RuleCall",
389205
389389
  "rule": {
389206
- "$ref": "#/rules@59"
389390
+ "$ref": "#/rules@64"
389207
389391
  },
389208
389392
  "arguments": []
389209
389393
  }
@@ -389247,7 +389431,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389247
389431
  "terminal": {
389248
389432
  "$type": "RuleCall",
389249
389433
  "rule": {
389250
- "$ref": "#/rules@23"
389434
+ "$ref": "#/rules@26"
389251
389435
  },
389252
389436
  "arguments": []
389253
389437
  },
@@ -389260,7 +389444,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389260
389444
  "terminal": {
389261
389445
  "$type": "RuleCall",
389262
389446
  "rule": {
389263
- "$ref": "#/rules@24"
389447
+ "$ref": "#/rules@27"
389264
389448
  },
389265
389449
  "arguments": []
389266
389450
  },
@@ -389273,7 +389457,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389273
389457
  "terminal": {
389274
389458
  "$type": "RuleCall",
389275
389459
  "rule": {
389276
- "$ref": "#/rules@25"
389460
+ "$ref": "#/rules@28"
389277
389461
  },
389278
389462
  "arguments": []
389279
389463
  },
@@ -389361,7 +389545,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389361
389545
  "terminal": {
389362
389546
  "$type": "RuleCall",
389363
389547
  "rule": {
389364
- "$ref": "#/rules@26"
389548
+ "$ref": "#/rules@29"
389365
389549
  },
389366
389550
  "arguments": []
389367
389551
  }
@@ -389373,7 +389557,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389373
389557
  "terminal": {
389374
389558
  "$type": "RuleCall",
389375
389559
  "rule": {
389376
- "$ref": "#/rules@27"
389560
+ "$ref": "#/rules@30"
389377
389561
  },
389378
389562
  "arguments": []
389379
389563
  }
@@ -389385,7 +389569,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389385
389569
  "terminal": {
389386
389570
  "$type": "RuleCall",
389387
389571
  "rule": {
389388
- "$ref": "#/rules@29"
389572
+ "$ref": "#/rules@32"
389389
389573
  },
389390
389574
  "arguments": []
389391
389575
  }
@@ -389422,7 +389606,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389422
389606
  "terminal": {
389423
389607
  "$type": "RuleCall",
389424
389608
  "rule": {
389425
- "$ref": "#/rules@61"
389609
+ "$ref": "#/rules@66"
389426
389610
  },
389427
389611
  "arguments": []
389428
389612
  }
@@ -389441,7 +389625,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389441
389625
  "terminal": {
389442
389626
  "$type": "RuleCall",
389443
389627
  "rule": {
389444
- "$ref": "#/rules@59"
389628
+ "$ref": "#/rules@64"
389445
389629
  },
389446
389630
  "arguments": []
389447
389631
  }
@@ -389472,7 +389656,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389472
389656
  "terminal": {
389473
389657
  "$type": "RuleCall",
389474
389658
  "rule": {
389475
- "$ref": "#/rules@61"
389659
+ "$ref": "#/rules@66"
389476
389660
  },
389477
389661
  "arguments": []
389478
389662
  }
@@ -389488,7 +389672,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389488
389672
  "terminal": {
389489
389673
  "$type": "RuleCall",
389490
389674
  "rule": {
389491
- "$ref": "#/rules@61"
389675
+ "$ref": "#/rules@66"
389492
389676
  },
389493
389677
  "arguments": []
389494
389678
  }
@@ -389508,7 +389692,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389508
389692
  "terminal": {
389509
389693
  "$type": "RuleCall",
389510
389694
  "rule": {
389511
- "$ref": "#/rules@60"
389695
+ "$ref": "#/rules@65"
389512
389696
  },
389513
389697
  "arguments": []
389514
389698
  }
@@ -389524,7 +389708,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389524
389708
  "terminal": {
389525
389709
  "$type": "RuleCall",
389526
389710
  "rule": {
389527
- "$ref": "#/rules@60"
389711
+ "$ref": "#/rules@65"
389528
389712
  },
389529
389713
  "arguments": []
389530
389714
  }
@@ -389540,7 +389724,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389540
389724
  "terminal": {
389541
389725
  "$type": "RuleCall",
389542
389726
  "rule": {
389543
- "$ref": "#/rules@60"
389727
+ "$ref": "#/rules@65"
389544
389728
  },
389545
389729
  "arguments": []
389546
389730
  }
@@ -389563,7 +389747,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389563
389747
  "terminal": {
389564
389748
  "$type": "RuleCall",
389565
389749
  "rule": {
389566
- "$ref": "#/rules@61"
389750
+ "$ref": "#/rules@66"
389567
389751
  },
389568
389752
  "arguments": []
389569
389753
  }
@@ -389585,7 +389769,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389585
389769
  "terminal": {
389586
389770
  "$type": "RuleCall",
389587
389771
  "rule": {
389588
- "$ref": "#/rules@61"
389772
+ "$ref": "#/rules@66"
389589
389773
  },
389590
389774
  "arguments": []
389591
389775
  }
@@ -389616,7 +389800,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389616
389800
  "terminal": {
389617
389801
  "$type": "RuleCall",
389618
389802
  "rule": {
389619
- "$ref": "#/rules@59"
389803
+ "$ref": "#/rules@64"
389620
389804
  },
389621
389805
  "arguments": []
389622
389806
  }
@@ -389632,7 +389816,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389632
389816
  "terminal": {
389633
389817
  "$type": "RuleCall",
389634
389818
  "rule": {
389635
- "$ref": "#/rules@14"
389819
+ "$ref": "#/rules@16"
389636
389820
  },
389637
389821
  "arguments": []
389638
389822
  }
@@ -389660,7 +389844,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389660
389844
  "terminal": {
389661
389845
  "$type": "RuleCall",
389662
389846
  "rule": {
389663
- "$ref": "#/rules@59"
389847
+ "$ref": "#/rules@64"
389664
389848
  },
389665
389849
  "arguments": []
389666
389850
  }
@@ -389684,7 +389868,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389684
389868
  "terminal": {
389685
389869
  "$type": "RuleCall",
389686
389870
  "rule": {
389687
- "$ref": "#/rules@14"
389871
+ "$ref": "#/rules@16"
389688
389872
  },
389689
389873
  "arguments": []
389690
389874
  }
@@ -389709,7 +389893,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389709
389893
  "terminal": {
389710
389894
  "$type": "RuleCall",
389711
389895
  "rule": {
389712
- "$ref": "#/rules@14"
389896
+ "$ref": "#/rules@16"
389713
389897
  },
389714
389898
  "arguments": []
389715
389899
  }
@@ -389741,7 +389925,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389741
389925
  "terminal": {
389742
389926
  "$type": "RuleCall",
389743
389927
  "rule": {
389744
- "$ref": "#/rules@59"
389928
+ "$ref": "#/rules@64"
389745
389929
  },
389746
389930
  "arguments": []
389747
389931
  }
@@ -389860,14 +390044,14 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389860
390044
  {
389861
390045
  "$type": "RuleCall",
389862
390046
  "rule": {
389863
- "$ref": "#/rules@59"
390047
+ "$ref": "#/rules@64"
389864
390048
  },
389865
390049
  "arguments": []
389866
390050
  },
389867
390051
  {
389868
390052
  "$type": "RuleCall",
389869
390053
  "rule": {
389870
- "$ref": "#/rules@60"
390054
+ "$ref": "#/rules@65"
389871
390055
  },
389872
390056
  "arguments": []
389873
390057
  }
@@ -389885,7 +390069,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389885
390069
  "terminal": {
389886
390070
  "$type": "RuleCall",
389887
390071
  "rule": {
389888
- "$ref": "#/rules@14"
390072
+ "$ref": "#/rules@16"
389889
390073
  },
389890
390074
  "arguments": []
389891
390075
  }
@@ -389904,7 +390088,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389904
390088
  "terminal": {
389905
390089
  "$type": "RuleCall",
389906
390090
  "rule": {
389907
- "$ref": "#/rules@14"
390091
+ "$ref": "#/rules@16"
389908
390092
  },
389909
390093
  "arguments": []
389910
390094
  }
@@ -389960,9 +390144,53 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389960
390144
  "$type": "Keyword",
389961
390145
  "value": "{"
389962
390146
  },
390147
+ {
390148
+ "$type": "Group",
390149
+ "elements": [
390150
+ {
390151
+ "$type": "Keyword",
390152
+ "value": "title"
390153
+ },
390154
+ {
390155
+ "$type": "Assignment",
390156
+ "feature": "title",
390157
+ "operator": "=",
390158
+ "terminal": {
390159
+ "$type": "RuleCall",
390160
+ "rule": {
390161
+ "$ref": "#/rules@66"
390162
+ },
390163
+ "arguments": []
390164
+ }
390165
+ }
390166
+ ],
390167
+ "cardinality": "?"
390168
+ },
390169
+ {
390170
+ "$type": "Group",
390171
+ "elements": [
390172
+ {
390173
+ "$type": "Keyword",
390174
+ "value": "note"
390175
+ },
390176
+ {
390177
+ "$type": "Assignment",
390178
+ "feature": "description",
390179
+ "operator": "=",
390180
+ "terminal": {
390181
+ "$type": "RuleCall",
390182
+ "rule": {
390183
+ "$ref": "#/rules@66"
390184
+ },
390185
+ "arguments": []
390186
+ }
390187
+ }
390188
+ ],
390189
+ "cardinality": "?"
390190
+ },
389963
390191
  {
389964
390192
  "$type": "Assignment",
389965
- "feature": "inputs",
390193
+ "feature": "items",
389966
390194
  "operator": "+=",
389967
390195
  "terminal": {
389968
390196
  "$type": "RuleCall",
@@ -389985,7 +390213,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
389985
390213
  },
389986
390214
  {
389987
390215
  "$type": "ParserRule",
389988
- "name": "ConfigInput",
390216
+ "name": "ConfigItem",
389989
390217
  "definition": {
389990
390218
  "$type": "Alternatives",
389991
390219
  "elements": [
@@ -390002,7 +390230,90 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390002
390230
  "$ref": "#/rules@10"
390003
390231
  },
390004
390232
  "arguments": []
390233
+ }
390234
+ ]
390235
+ },
390236
+ "entry": false,
390237
+ "fragment": false,
390238
+ "parameters": []
390239
+ },
390240
+ {
390241
+ "$type": "ParserRule",
390242
+ "name": "ConfigGroup",
390243
+ "definition": {
390244
+ "$type": "Group",
390245
+ "elements": [
390246
+ {
390247
+ "$type": "Keyword",
390248
+ "value": "group"
390005
390249
  },
390250
+ {
390251
+ "$type": "Assignment",
390252
+ "feature": "label",
390253
+ "operator": "=",
390254
+ "terminal": {
390255
+ "$type": "RuleCall",
390256
+ "rule": {
390257
+ "$ref": "#/rules@66"
390258
+ },
390259
+ "arguments": []
390260
+ }
390261
+ },
390262
+ {
390263
+ "$type": "Group",
390264
+ "elements": [
390265
+ {
390266
+ "$type": "Keyword",
390267
+ "value": "note"
390268
+ },
390269
+ {
390270
+ "$type": "Assignment",
390271
+ "feature": "description",
390272
+ "operator": "=",
390273
+ "terminal": {
390274
+ "$type": "RuleCall",
390275
+ "rule": {
390276
+ "$ref": "#/rules@66"
390277
+ },
390278
+ "arguments": []
390279
+ }
390280
+ }
390281
+ ],
390282
+ "cardinality": "?"
390283
+ },
390284
+ {
390285
+ "$type": "Keyword",
390286
+ "value": "{"
390287
+ },
390288
+ {
390289
+ "$type": "Assignment",
390290
+ "feature": "inputs",
390291
+ "operator": "+=",
390292
+ "terminal": {
390293
+ "$type": "RuleCall",
390294
+ "rule": {
390295
+ "$ref": "#/rules@10"
390296
+ },
390297
+ "arguments": []
390298
+ },
390299
+ "cardinality": "+"
390300
+ },
390301
+ {
390302
+ "$type": "Keyword",
390303
+ "value": "}"
390304
+ }
390305
+ ]
390306
+ },
390307
+ "entry": false,
390308
+ "fragment": false,
390309
+ "parameters": []
390310
+ },
390311
+ {
390312
+ "$type": "ParserRule",
390313
+ "name": "ConfigInput",
390314
+ "definition": {
390315
+ "$type": "Alternatives",
390316
+ "elements": [
390006
390317
  {
390007
390318
  "$type": "RuleCall",
390008
390319
  "rule": {
@@ -390016,6 +390327,20 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390016
390327
  "$ref": "#/rules@12"
390017
390328
  },
390018
390329
  "arguments": []
390330
+ },
390331
+ {
390332
+ "$type": "RuleCall",
390333
+ "rule": {
390334
+ "$ref": "#/rules@13"
390335
+ },
390336
+ "arguments": []
390337
+ },
390338
+ {
390339
+ "$type": "RuleCall",
390340
+ "rule": {
390341
+ "$ref": "#/rules@14"
390342
+ },
390343
+ "arguments": []
390019
390344
  }
390020
390345
  ]
390021
390346
  },
@@ -390040,7 +390365,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390040
390365
  "terminal": {
390041
390366
  "$type": "RuleCall",
390042
390367
  "rule": {
390043
- "$ref": "#/rules@59"
390368
+ "$ref": "#/rules@64"
390044
390369
  },
390045
390370
  "arguments": []
390046
390371
  }
@@ -390052,7 +390377,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390052
390377
  "terminal": {
390053
390378
  "$type": "RuleCall",
390054
390379
  "rule": {
390055
- "$ref": "#/rules@61"
390380
+ "$ref": "#/rules@66"
390056
390381
  },
390057
390382
  "arguments": []
390058
390383
  }
@@ -390064,7 +390389,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390064
390389
  "terminal": {
390065
390390
  "$type": "RuleCall",
390066
390391
  "rule": {
390067
- "$ref": "#/rules@59"
390392
+ "$ref": "#/rules@64"
390068
390393
  },
390069
390394
  "arguments": []
390070
390395
  },
@@ -390081,7 +390406,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390081
390406
  "terminal": {
390082
390407
  "$type": "RuleCall",
390083
390408
  "rule": {
390084
- "$ref": "#/rules@60"
390409
+ "$ref": "#/rules@65"
390085
390410
  },
390086
390411
  "arguments": []
390087
390412
  }
@@ -390097,7 +390422,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390097
390422
  "terminal": {
390098
390423
  "$type": "RuleCall",
390099
390424
  "rule": {
390100
- "$ref": "#/rules@60"
390425
+ "$ref": "#/rules@65"
390101
390426
  },
390102
390427
  "arguments": []
390103
390428
  }
@@ -390116,7 +390441,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390116
390441
  "terminal": {
390117
390442
  "$type": "RuleCall",
390118
390443
  "rule": {
390119
- "$ref": "#/rules@60"
390444
+ "$ref": "#/rules@65"
390120
390445
  },
390121
390446
  "arguments": []
390122
390447
  }
@@ -390127,6 +390452,28 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390127
390452
  {
390128
390453
  "$type": "Keyword",
390129
390454
  "value": "]"
390455
+ },
390456
+ {
390457
+ "$type": "Group",
390458
+ "elements": [
390459
+ {
390460
+ "$type": "Keyword",
390461
+ "value": "note"
390462
+ },
390463
+ {
390464
+ "$type": "Assignment",
390465
+ "feature": "description",
390466
+ "operator": "=",
390467
+ "terminal": {
390468
+ "$type": "RuleCall",
390469
+ "rule": {
390470
+ "$ref": "#/rules@66"
390471
+ },
390472
+ "arguments": []
390473
+ }
390474
+ }
390475
+ ],
390476
+ "cardinality": "?"
390130
390477
  }
390131
390478
  ]
390132
390479
  },
@@ -390151,7 +390498,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390151
390498
  "terminal": {
390152
390499
  "$type": "RuleCall",
390153
390500
  "rule": {
390154
- "$ref": "#/rules@59"
390501
+ "$ref": "#/rules@64"
390155
390502
  },
390156
390503
  "arguments": []
390157
390504
  }
@@ -390163,7 +390510,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390163
390510
  "terminal": {
390164
390511
  "$type": "RuleCall",
390165
390512
  "rule": {
390166
- "$ref": "#/rules@61"
390513
+ "$ref": "#/rules@66"
390167
390514
  },
390168
390515
  "arguments": []
390169
390516
  }
@@ -390175,11 +390522,33 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390175
390522
  "terminal": {
390176
390523
  "$type": "RuleCall",
390177
390524
  "rule": {
390178
- "$ref": "#/rules@59"
390525
+ "$ref": "#/rules@64"
390179
390526
  },
390180
390527
  "arguments": []
390181
390528
  },
390182
390529
  "cardinality": "?"
390530
+ },
390531
+ {
390532
+ "$type": "Group",
390533
+ "elements": [
390534
+ {
390535
+ "$type": "Keyword",
390536
+ "value": "note"
390537
+ },
390538
+ {
390539
+ "$type": "Assignment",
390540
+ "feature": "description",
390541
+ "operator": "=",
390542
+ "terminal": {
390543
+ "$type": "RuleCall",
390544
+ "rule": {
390545
+ "$ref": "#/rules@66"
390546
+ },
390547
+ "arguments": []
390548
+ }
390549
+ }
390550
+ ],
390551
+ "cardinality": "?"
390183
390552
  }
390184
390553
  ]
390185
390554
  },
@@ -390204,7 +390573,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390204
390573
  "terminal": {
390205
390574
  "$type": "RuleCall",
390206
390575
  "rule": {
390207
- "$ref": "#/rules@59"
390576
+ "$ref": "#/rules@64"
390208
390577
  },
390209
390578
  "arguments": []
390210
390579
  }
@@ -390216,10 +390585,32 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390216
390585
  "terminal": {
390217
390586
  "$type": "RuleCall",
390218
390587
  "rule": {
390219
- "$ref": "#/rules@61"
390588
+ "$ref": "#/rules@66"
390220
390589
  },
390221
390590
  "arguments": []
390222
390591
  }
390592
+ },
390593
+ {
390594
+ "$type": "Group",
390595
+ "elements": [
390596
+ {
390597
+ "$type": "Keyword",
390598
+ "value": "note"
390599
+ },
390600
+ {
390601
+ "$type": "Assignment",
390602
+ "feature": "description",
390603
+ "operator": "=",
390604
+ "terminal": {
390605
+ "$type": "RuleCall",
390606
+ "rule": {
390607
+ "$ref": "#/rules@66"
390608
+ },
390609
+ "arguments": []
390610
+ }
390611
+ }
390612
+ ],
390613
+ "cardinality": "?"
390223
390614
  }
390224
390615
  ]
390225
390616
  },
@@ -390244,7 +390635,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390244
390635
  "terminal": {
390245
390636
  "$type": "RuleCall",
390246
390637
  "rule": {
390247
- "$ref": "#/rules@59"
390638
+ "$ref": "#/rules@64"
390248
390639
  },
390249
390640
  "arguments": []
390250
390641
  }
@@ -390256,7 +390647,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390256
390647
  "terminal": {
390257
390648
  "$type": "RuleCall",
390258
390649
  "rule": {
390259
- "$ref": "#/rules@61"
390650
+ "$ref": "#/rules@66"
390260
390651
  },
390261
390652
  "arguments": []
390262
390653
  }
@@ -390272,7 +390663,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390272
390663
  "terminal": {
390273
390664
  "$type": "RuleCall",
390274
390665
  "rule": {
390275
- "$ref": "#/rules@13"
390666
+ "$ref": "#/rules@15"
390276
390667
  },
390277
390668
  "arguments": []
390278
390669
  }
@@ -390291,7 +390682,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390291
390682
  "terminal": {
390292
390683
  "$type": "RuleCall",
390293
390684
  "rule": {
390294
- "$ref": "#/rules@13"
390685
+ "$ref": "#/rules@15"
390295
390686
  },
390296
390687
  "arguments": []
390297
390688
  }
@@ -390302,6 +390693,28 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390302
390693
  {
390303
390694
  "$type": "Keyword",
390304
390695
  "value": "}"
390696
+ },
390697
+ {
390698
+ "$type": "Group",
390699
+ "elements": [
390700
+ {
390701
+ "$type": "Keyword",
390702
+ "value": "note"
390703
+ },
390704
+ {
390705
+ "$type": "Assignment",
390706
+ "feature": "description",
390707
+ "operator": "=",
390708
+ "terminal": {
390709
+ "$type": "RuleCall",
390710
+ "rule": {
390711
+ "$ref": "#/rules@66"
390712
+ },
390713
+ "arguments": []
390714
+ }
390715
+ }
390716
+ ],
390717
+ "cardinality": "?"
390305
390718
  }
390306
390719
  ]
390307
390720
  },
@@ -390320,11 +390733,23 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390320
390733
  "feature": "label",
390321
390734
  "operator": "=",
390322
390735
  "terminal": {
390323
- "$type": "RuleCall",
390324
- "rule": {
390325
- "$ref": "#/rules@59"
390326
- },
390327
- "arguments": []
390736
+ "$type": "Alternatives",
390737
+ "elements": [
390738
+ {
390739
+ "$type": "RuleCall",
390740
+ "rule": {
390741
+ "$ref": "#/rules@64"
390742
+ },
390743
+ "arguments": []
390744
+ },
390745
+ {
390746
+ "$type": "RuleCall",
390747
+ "rule": {
390748
+ "$ref": "#/rules@66"
390749
+ },
390750
+ "arguments": []
390751
+ }
390752
+ ]
390328
390753
  }
390329
390754
  },
390330
390755
  {
@@ -390338,7 +390763,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390338
390763
  "terminal": {
390339
390764
  "$type": "RuleCall",
390340
390765
  "rule": {
390341
- "$ref": "#/rules@60"
390766
+ "$ref": "#/rules@65"
390342
390767
  },
390343
390768
  "arguments": []
390344
390769
  }
@@ -390359,7 +390784,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390359
390784
  "definition": {
390360
390785
  "$type": "RuleCall",
390361
390786
  "rule": {
390362
- "$ref": "#/rules@15"
390787
+ "$ref": "#/rules@17"
390363
390788
  },
390364
390789
  "arguments": []
390365
390790
  },
@@ -390380,7 +390805,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390380
390805
  {
390381
390806
  "$type": "RuleCall",
390382
390807
  "rule": {
390383
- "$ref": "#/rules@16"
390808
+ "$ref": "#/rules@18"
390384
390809
  },
390385
390810
  "arguments": []
390386
390811
  },
@@ -390421,7 +390846,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390421
390846
  "terminal": {
390422
390847
  "$type": "RuleCall",
390423
390848
  "rule": {
390424
- "$ref": "#/rules@16"
390849
+ "$ref": "#/rules@18"
390425
390850
  },
390426
390851
  "arguments": []
390427
390852
  }
@@ -390448,7 +390873,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390448
390873
  {
390449
390874
  "$type": "RuleCall",
390450
390875
  "rule": {
390451
- "$ref": "#/rules@17"
390876
+ "$ref": "#/rules@19"
390452
390877
  },
390453
390878
  "arguments": []
390454
390879
  },
@@ -390489,7 +390914,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390489
390914
  "terminal": {
390490
390915
  "$type": "RuleCall",
390491
390916
  "rule": {
390492
- "$ref": "#/rules@17"
390917
+ "$ref": "#/rules@19"
390493
390918
  },
390494
390919
  "arguments": []
390495
390920
  }
@@ -390534,7 +390959,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390534
390959
  "terminal": {
390535
390960
  "$type": "RuleCall",
390536
390961
  "rule": {
390537
- "$ref": "#/rules@17"
390962
+ "$ref": "#/rules@19"
390538
390963
  },
390539
390964
  "arguments": []
390540
390965
  }
@@ -390551,7 +390976,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390551
390976
  {
390552
390977
  "$type": "RuleCall",
390553
390978
  "rule": {
390554
- "$ref": "#/rules@14"
390979
+ "$ref": "#/rules@16"
390555
390980
  },
390556
390981
  "arguments": []
390557
390982
  },
@@ -390578,7 +391003,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390578
391003
  "terminal": {
390579
391004
  "$type": "RuleCall",
390580
391005
  "rule": {
390581
- "$ref": "#/rules@60"
391006
+ "$ref": "#/rules@65"
390582
391007
  },
390583
391008
  "arguments": []
390584
391009
  }
@@ -390588,7 +391013,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390588
391013
  {
390589
391014
  "$type": "RuleCall",
390590
391015
  "rule": {
390591
- "$ref": "#/rules@18"
391016
+ "$ref": "#/rules@20"
390592
391017
  },
390593
391018
  "arguments": []
390594
391019
  }
@@ -390622,7 +391047,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390622
391047
  "terminal": {
390623
391048
  "$type": "RuleCall",
390624
391049
  "rule": {
390625
- "$ref": "#/rules@59"
391050
+ "$ref": "#/rules@64"
390626
391051
  },
390627
391052
  "arguments": []
390628
391053
  }
@@ -390641,7 +391066,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390641
391066
  "terminal": {
390642
391067
  "$type": "RuleCall",
390643
391068
  "rule": {
390644
- "$ref": "#/rules@59"
391069
+ "$ref": "#/rules@21"
390645
391070
  },
390646
391071
  "arguments": []
390647
391072
  }
@@ -390675,7 +391100,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390675
391100
  "terminal": {
390676
391101
  "$type": "RuleCall",
390677
391102
  "rule": {
390678
- "$ref": "#/rules@14"
391103
+ "$ref": "#/rules@16"
390679
391104
  },
390680
391105
  "arguments": []
390681
391106
  }
@@ -390694,7 +391119,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390694
391119
  "terminal": {
390695
391120
  "$type": "RuleCall",
390696
391121
  "rule": {
390697
- "$ref": "#/rules@14"
391122
+ "$ref": "#/rules@16"
390698
391123
  },
390699
391124
  "arguments": []
390700
391125
  }
@@ -390718,6 +391143,34 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390718
391143
  "fragment": false,
390719
391144
  "parameters": []
390720
391145
  },
391146
+ {
391147
+ "$type": "ParserRule",
391148
+ "name": "RefPart",
391149
+ "dataType": "string",
391150
+ "definition": {
391151
+ "$type": "Alternatives",
391152
+ "elements": [
391153
+ {
391154
+ "$type": "RuleCall",
391155
+ "rule": {
391156
+ "$ref": "#/rules@64"
391157
+ },
391158
+ "arguments": []
391159
+ },
391160
+ {
391161
+ "$type": "Keyword",
391162
+ "value": "x"
391163
+ },
391164
+ {
391165
+ "$type": "Keyword",
391166
+ "value": "y"
391167
+ }
391168
+ ]
391169
+ },
391170
+ "entry": false,
391171
+ "fragment": false,
391172
+ "parameters": []
391173
+ },
390721
391174
  {
390722
391175
  "$type": "ParserRule",
390723
391176
  "name": "Raw",
@@ -390735,7 +391188,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390735
391188
  "terminal": {
390736
391189
  "$type": "RuleCall",
390737
391190
  "rule": {
390738
- "$ref": "#/rules@61"
391191
+ "$ref": "#/rules@66"
390739
391192
  },
390740
391193
  "arguments": []
390741
391194
  }
@@ -390747,7 +391200,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390747
391200
  "terminal": {
390748
391201
  "$type": "RuleCall",
390749
391202
  "rule": {
390750
- "$ref": "#/rules@20"
391203
+ "$ref": "#/rules@23"
390751
391204
  },
390752
391205
  "arguments": []
390753
391206
  }
@@ -390782,7 +391235,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390782
391235
  "terminal": {
390783
391236
  "$type": "RuleCall",
390784
391237
  "rule": {
390785
- "$ref": "#/rules@21"
391238
+ "$ref": "#/rules@24"
390786
391239
  },
390787
391240
  "arguments": []
390788
391241
  }
@@ -390801,7 +391254,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390801
391254
  "terminal": {
390802
391255
  "$type": "RuleCall",
390803
391256
  "rule": {
390804
- "$ref": "#/rules@21"
391257
+ "$ref": "#/rules@24"
390805
391258
  },
390806
391259
  "arguments": []
390807
391260
  }
@@ -390838,14 +391291,14 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390838
391291
  {
390839
391292
  "$type": "RuleCall",
390840
391293
  "rule": {
390841
- "$ref": "#/rules@61"
391294
+ "$ref": "#/rules@66"
390842
391295
  },
390843
391296
  "arguments": []
390844
391297
  },
390845
391298
  {
390846
391299
  "$type": "RuleCall",
390847
391300
  "rule": {
390848
- "$ref": "#/rules@59"
391301
+ "$ref": "#/rules@64"
390849
391302
  },
390850
391303
  "arguments": []
390851
391304
  }
@@ -390863,7 +391316,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390863
391316
  "terminal": {
390864
391317
  "$type": "RuleCall",
390865
391318
  "rule": {
390866
- "$ref": "#/rules@22"
391319
+ "$ref": "#/rules@25"
390867
391320
  },
390868
391321
  "arguments": []
390869
391322
  }
@@ -390887,7 +391340,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390887
391340
  {
390888
391341
  "$type": "RuleCall",
390889
391342
  "rule": {
390890
- "$ref": "#/rules@20"
391343
+ "$ref": "#/rules@23"
390891
391344
  },
390892
391345
  "arguments": []
390893
391346
  },
@@ -390915,7 +391368,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390915
391368
  "terminal": {
390916
391369
  "$type": "RuleCall",
390917
391370
  "rule": {
390918
- "$ref": "#/rules@22"
391371
+ "$ref": "#/rules@25"
390919
391372
  },
390920
391373
  "arguments": []
390921
391374
  }
@@ -390934,7 +391387,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390934
391387
  "terminal": {
390935
391388
  "$type": "RuleCall",
390936
391389
  "rule": {
390937
- "$ref": "#/rules@22"
391390
+ "$ref": "#/rules@25"
390938
391391
  },
390939
391392
  "arguments": []
390940
391393
  }
@@ -390978,7 +391431,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
390978
391431
  "terminal": {
390979
391432
  "$type": "RuleCall",
390980
391433
  "rule": {
390981
- "$ref": "#/rules@60"
391434
+ "$ref": "#/rules@65"
390982
391435
  },
390983
391436
  "arguments": []
390984
391437
  }
@@ -391002,7 +391455,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391002
391455
  "terminal": {
391003
391456
  "$type": "RuleCall",
391004
391457
  "rule": {
391005
- "$ref": "#/rules@61"
391458
+ "$ref": "#/rules@66"
391006
391459
  },
391007
391460
  "arguments": []
391008
391461
  }
@@ -391115,7 +391568,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391115
391568
  "terminal": {
391116
391569
  "$type": "RuleCall",
391117
391570
  "rule": {
391118
- "$ref": "#/rules@60"
391571
+ "$ref": "#/rules@65"
391119
391572
  },
391120
391573
  "arguments": []
391121
391574
  }
@@ -391158,7 +391611,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391158
391611
  "terminal": {
391159
391612
  "$type": "RuleCall",
391160
391613
  "rule": {
391161
- "$ref": "#/rules@14"
391614
+ "$ref": "#/rules@16"
391162
391615
  },
391163
391616
  "arguments": []
391164
391617
  }
@@ -391174,7 +391627,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391174
391627
  "terminal": {
391175
391628
  "$type": "RuleCall",
391176
391629
  "rule": {
391177
- "$ref": "#/rules@14"
391630
+ "$ref": "#/rules@16"
391178
391631
  },
391179
391632
  "arguments": []
391180
391633
  }
@@ -391201,7 +391654,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391201
391654
  "terminal": {
391202
391655
  "$type": "RuleCall",
391203
391656
  "rule": {
391204
- "$ref": "#/rules@60"
391657
+ "$ref": "#/rules@65"
391205
391658
  },
391206
391659
  "arguments": []
391207
391660
  }
@@ -391217,7 +391670,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391217
391670
  "terminal": {
391218
391671
  "$type": "RuleCall",
391219
391672
  "rule": {
391220
- "$ref": "#/rules@60"
391673
+ "$ref": "#/rules@65"
391221
391674
  },
391222
391675
  "arguments": []
391223
391676
  }
@@ -391267,7 +391720,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391267
391720
  "terminal": {
391268
391721
  "$type": "RuleCall",
391269
391722
  "rule": {
391270
- "$ref": "#/rules@60"
391723
+ "$ref": "#/rules@65"
391271
391724
  },
391272
391725
  "arguments": []
391273
391726
  }
@@ -391289,7 +391742,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391289
391742
  "terminal": {
391290
391743
  "$type": "RuleCall",
391291
391744
  "rule": {
391292
- "$ref": "#/rules@60"
391745
+ "$ref": "#/rules@65"
391293
391746
  },
391294
391747
  "arguments": []
391295
391748
  }
@@ -391311,7 +391764,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391311
391764
  "terminal": {
391312
391765
  "$type": "RuleCall",
391313
391766
  "rule": {
391314
- "$ref": "#/rules@60"
391767
+ "$ref": "#/rules@65"
391315
391768
  },
391316
391769
  "arguments": []
391317
391770
  }
@@ -391333,7 +391786,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391333
391786
  "terminal": {
391334
391787
  "$type": "RuleCall",
391335
391788
  "rule": {
391336
- "$ref": "#/rules@60"
391789
+ "$ref": "#/rules@65"
391337
391790
  },
391338
391791
  "arguments": []
391339
391792
  }
@@ -391368,7 +391821,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391368
391821
  "terminal": {
391369
391822
  "$type": "RuleCall",
391370
391823
  "rule": {
391371
- "$ref": "#/rules@61"
391824
+ "$ref": "#/rules@66"
391372
391825
  },
391373
391826
  "arguments": []
391374
391827
  }
@@ -391380,7 +391833,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391380
391833
  "terminal": {
391381
391834
  "$type": "RuleCall",
391382
391835
  "rule": {
391383
- "$ref": "#/rules@61"
391836
+ "$ref": "#/rules@66"
391384
391837
  },
391385
391838
  "arguments": []
391386
391839
  }
@@ -391399,7 +391852,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391399
391852
  "terminal": {
391400
391853
  "$type": "RuleCall",
391401
391854
  "rule": {
391402
- "$ref": "#/rules@61"
391855
+ "$ref": "#/rules@66"
391403
391856
  },
391404
391857
  "arguments": []
391405
391858
  }
@@ -391421,7 +391874,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391421
391874
  "terminal": {
391422
391875
  "$type": "RuleCall",
391423
391876
  "rule": {
391424
- "$ref": "#/rules@61"
391877
+ "$ref": "#/rules@66"
391425
391878
  },
391426
391879
  "arguments": []
391427
391880
  }
@@ -391452,7 +391905,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391452
391905
  "terminal": {
391453
391906
  "$type": "RuleCall",
391454
391907
  "rule": {
391455
- "$ref": "#/rules@59"
391908
+ "$ref": "#/rules@64"
391456
391909
  },
391457
391910
  "arguments": []
391458
391911
  }
@@ -391471,7 +391924,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391471
391924
  "terminal": {
391472
391925
  "$type": "RuleCall",
391473
391926
  "rule": {
391474
- "$ref": "#/rules@61"
391927
+ "$ref": "#/rules@66"
391475
391928
  },
391476
391929
  "arguments": []
391477
391930
  }
@@ -391490,7 +391943,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391490
391943
  "terminal": {
391491
391944
  "$type": "RuleCall",
391492
391945
  "rule": {
391493
- "$ref": "#/rules@28"
391946
+ "$ref": "#/rules@31"
391494
391947
  },
391495
391948
  "arguments": []
391496
391949
  },
@@ -391533,7 +391986,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391533
391986
  "terminal": {
391534
391987
  "$type": "RuleCall",
391535
391988
  "rule": {
391536
- "$ref": "#/rules@30"
391989
+ "$ref": "#/rules@33"
391537
391990
  },
391538
391991
  "arguments": []
391539
391992
  },
@@ -391566,7 +392019,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391566
392019
  "terminal": {
391567
392020
  "$type": "RuleCall",
391568
392021
  "rule": {
391569
- "$ref": "#/rules@59"
392022
+ "$ref": "#/rules@64"
391570
392023
  },
391571
392024
  "arguments": []
391572
392025
  }
@@ -391585,7 +392038,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391585
392038
  "terminal": {
391586
392039
  "$type": "RuleCall",
391587
392040
  "rule": {
391588
- "$ref": "#/rules@60"
392041
+ "$ref": "#/rules@65"
391589
392042
  },
391590
392043
  "arguments": []
391591
392044
  }
@@ -391607,7 +392060,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391607
392060
  "terminal": {
391608
392061
  "$type": "RuleCall",
391609
392062
  "rule": {
391610
- "$ref": "#/rules@61"
392063
+ "$ref": "#/rules@66"
391611
392064
  },
391612
392065
  "arguments": []
391613
392066
  }
@@ -391638,7 +392091,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391638
392091
  "terminal": {
391639
392092
  "$type": "RuleCall",
391640
392093
  "rule": {
391641
- "$ref": "#/rules@60"
392094
+ "$ref": "#/rules@65"
391642
392095
  },
391643
392096
  "arguments": []
391644
392097
  }
@@ -391650,7 +392103,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391650
392103
  "terminal": {
391651
392104
  "$type": "RuleCall",
391652
392105
  "rule": {
391653
- "$ref": "#/rules@61"
392106
+ "$ref": "#/rules@66"
391654
392107
  },
391655
392108
  "arguments": []
391656
392109
  }
@@ -391669,7 +392122,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391669
392122
  "terminal": {
391670
392123
  "$type": "RuleCall",
391671
392124
  "rule": {
391672
- "$ref": "#/rules@60"
392125
+ "$ref": "#/rules@65"
391673
392126
  },
391674
392127
  "arguments": []
391675
392128
  }
@@ -391691,7 +392144,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391691
392144
  "terminal": {
391692
392145
  "$type": "RuleCall",
391693
392146
  "rule": {
391694
- "$ref": "#/rules@60"
392147
+ "$ref": "#/rules@65"
391695
392148
  },
391696
392149
  "arguments": []
391697
392150
  }
@@ -391713,7 +392166,29 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391713
392166
  "terminal": {
391714
392167
  "$type": "RuleCall",
391715
392168
  "rule": {
391716
- "$ref": "#/rules@60"
392169
+ "$ref": "#/rules@65"
392170
+ },
392171
+ "arguments": []
392172
+ }
392173
+ }
392174
+ ],
392175
+ "cardinality": "?"
392176
+ },
392177
+ {
392178
+ "$type": "Group",
392179
+ "elements": [
392180
+ {
392181
+ "$type": "Keyword",
392182
+ "value": "enabled"
392183
+ },
392184
+ {
392185
+ "$type": "Assignment",
392186
+ "feature": "enabled",
392187
+ "operator": "=",
392188
+ "terminal": {
392189
+ "$type": "RuleCall",
392190
+ "rule": {
392191
+ "$ref": "#/rules@16"
391717
392192
  },
391718
392193
  "arguments": []
391719
392194
  }
@@ -391732,7 +392207,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391732
392207
  "terminal": {
391733
392208
  "$type": "RuleCall",
391734
392209
  "rule": {
391735
- "$ref": "#/rules@30"
392210
+ "$ref": "#/rules@33"
391736
392211
  },
391737
392212
  "arguments": []
391738
392213
  },
@@ -391757,91 +392232,91 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391757
392232
  {
391758
392233
  "$type": "RuleCall",
391759
392234
  "rule": {
391760
- "$ref": "#/rules@32"
392235
+ "$ref": "#/rules@36"
391761
392236
  },
391762
392237
  "arguments": []
391763
392238
  },
391764
392239
  {
391765
392240
  "$type": "RuleCall",
391766
392241
  "rule": {
391767
- "$ref": "#/rules@36"
392242
+ "$ref": "#/rules@40"
391768
392243
  },
391769
392244
  "arguments": []
391770
392245
  },
391771
392246
  {
391772
392247
  "$type": "RuleCall",
391773
392248
  "rule": {
391774
- "$ref": "#/rules@37"
392249
+ "$ref": "#/rules@41"
391775
392250
  },
391776
392251
  "arguments": []
391777
392252
  },
391778
392253
  {
391779
392254
  "$type": "RuleCall",
391780
392255
  "rule": {
391781
- "$ref": "#/rules@38"
392256
+ "$ref": "#/rules@42"
391782
392257
  },
391783
392258
  "arguments": []
391784
392259
  },
391785
392260
  {
391786
392261
  "$type": "RuleCall",
391787
392262
  "rule": {
391788
- "$ref": "#/rules@39"
392263
+ "$ref": "#/rules@43"
391789
392264
  },
391790
392265
  "arguments": []
391791
392266
  },
391792
392267
  {
391793
392268
  "$type": "RuleCall",
391794
392269
  "rule": {
391795
- "$ref": "#/rules@40"
392270
+ "$ref": "#/rules@44"
391796
392271
  },
391797
392272
  "arguments": []
391798
392273
  },
391799
392274
  {
391800
392275
  "$type": "RuleCall",
391801
392276
  "rule": {
391802
- "$ref": "#/rules@41"
392277
+ "$ref": "#/rules@45"
391803
392278
  },
391804
392279
  "arguments": []
391805
392280
  },
391806
392281
  {
391807
392282
  "$type": "RuleCall",
391808
392283
  "rule": {
391809
- "$ref": "#/rules@42"
392284
+ "$ref": "#/rules@46"
391810
392285
  },
391811
392286
  "arguments": []
391812
392287
  },
391813
392288
  {
391814
392289
  "$type": "RuleCall",
391815
392290
  "rule": {
391816
- "$ref": "#/rules@43"
392291
+ "$ref": "#/rules@47"
391817
392292
  },
391818
392293
  "arguments": []
391819
392294
  },
391820
392295
  {
391821
392296
  "$type": "RuleCall",
391822
392297
  "rule": {
391823
- "$ref": "#/rules@45"
392298
+ "$ref": "#/rules@49"
391824
392299
  },
391825
392300
  "arguments": []
391826
392301
  },
391827
392302
  {
391828
392303
  "$type": "RuleCall",
391829
392304
  "rule": {
391830
- "$ref": "#/rules@50"
392305
+ "$ref": "#/rules@54"
391831
392306
  },
391832
392307
  "arguments": []
391833
392308
  },
391834
392309
  {
391835
392310
  "$type": "RuleCall",
391836
392311
  "rule": {
391837
- "$ref": "#/rules@52"
392312
+ "$ref": "#/rules@57"
391838
392313
  },
391839
392314
  "arguments": []
391840
392315
  },
391841
392316
  {
391842
392317
  "$type": "RuleCall",
391843
392318
  "rule": {
391844
- "$ref": "#/rules@19"
392319
+ "$ref": "#/rules@22"
391845
392320
  },
391846
392321
  "arguments": []
391847
392322
  }
@@ -391872,7 +392347,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391872
392347
  "terminal": {
391873
392348
  "$type": "RuleCall",
391874
392349
  "rule": {
391875
- "$ref": "#/rules@14"
392350
+ "$ref": "#/rules@16"
391876
392351
  },
391877
392352
  "arguments": []
391878
392353
  }
@@ -391894,7 +392369,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391894
392369
  "terminal": {
391895
392370
  "$type": "RuleCall",
391896
392371
  "rule": {
391897
- "$ref": "#/rules@14"
392372
+ "$ref": "#/rules@16"
391898
392373
  },
391899
392374
  "arguments": []
391900
392375
  }
@@ -391916,7 +392391,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391916
392391
  "terminal": {
391917
392392
  "$type": "RuleCall",
391918
392393
  "rule": {
391919
- "$ref": "#/rules@61"
392394
+ "$ref": "#/rules@66"
391920
392395
  },
391921
392396
  "arguments": []
391922
392397
  }
@@ -391929,6 +392404,33 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391929
392404
  "entry": false,
391930
392405
  "parameters": []
391931
392406
  },
392407
+ {
392408
+ "$type": "ParserRule",
392409
+ "name": "NameRef",
392410
+ "dataType": "string",
392411
+ "definition": {
392412
+ "$type": "Alternatives",
392413
+ "elements": [
392414
+ {
392415
+ "$type": "RuleCall",
392416
+ "rule": {
392417
+ "$ref": "#/rules@64"
392418
+ },
392419
+ "arguments": []
392420
+ },
392421
+ {
392422
+ "$type": "RuleCall",
392423
+ "rule": {
392424
+ "$ref": "#/rules@66"
392425
+ },
392426
+ "arguments": []
392427
+ }
392428
+ ]
392429
+ },
392430
+ "entry": false,
392431
+ "fragment": false,
392432
+ "parameters": []
392433
+ },
391932
392434
  {
391933
392435
  "$type": "ParserRule",
391934
392436
  "name": "Room",
@@ -391946,7 +392448,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391946
392448
  "terminal": {
391947
392449
  "$type": "RuleCall",
391948
392450
  "rule": {
391949
- "$ref": "#/rules@59"
392451
+ "$ref": "#/rules@35"
391950
392452
  },
391951
392453
  "arguments": []
391952
392454
  }
@@ -391966,7 +392468,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391966
392468
  "terminal": {
391967
392469
  "$type": "RuleCall",
391968
392470
  "rule": {
391969
- "$ref": "#/rules@14"
392471
+ "$ref": "#/rules@16"
391970
392472
  },
391971
392473
  "arguments": []
391972
392474
  }
@@ -391982,7 +392484,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
391982
392484
  "terminal": {
391983
392485
  "$type": "RuleCall",
391984
392486
  "rule": {
391985
- "$ref": "#/rules@14"
392487
+ "$ref": "#/rules@16"
391986
392488
  },
391987
392489
  "arguments": []
391988
392490
  }
@@ -392006,7 +392508,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392006
392508
  "terminal": {
392007
392509
  "$type": "RuleCall",
392008
392510
  "rule": {
392009
- "$ref": "#/rules@14"
392511
+ "$ref": "#/rules@16"
392010
392512
  },
392011
392513
  "arguments": []
392012
392514
  }
@@ -392022,7 +392524,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392022
392524
  "terminal": {
392023
392525
  "$type": "RuleCall",
392024
392526
  "rule": {
392025
- "$ref": "#/rules@14"
392527
+ "$ref": "#/rules@16"
392026
392528
  },
392027
392529
  "arguments": []
392028
392530
  }
@@ -392045,7 +392547,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392045
392547
  "terminal": {
392046
392548
  "$type": "RuleCall",
392047
392549
  "rule": {
392048
- "$ref": "#/rules@14"
392550
+ "$ref": "#/rules@16"
392049
392551
  },
392050
392552
  "arguments": []
392051
392553
  }
@@ -392056,7 +392558,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392056
392558
  {
392057
392559
  "$type": "RuleCall",
392058
392560
  "rule": {
392059
- "$ref": "#/rules@31"
392561
+ "$ref": "#/rules@34"
392060
392562
  },
392061
392563
  "arguments": []
392062
392564
  },
@@ -392074,7 +392576,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392074
392576
  "terminal": {
392075
392577
  "$type": "RuleCall",
392076
392578
  "rule": {
392077
- "$ref": "#/rules@61"
392579
+ "$ref": "#/rules@66"
392078
392580
  },
392079
392581
  "arguments": []
392080
392582
  }
@@ -392099,7 +392601,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392099
392601
  "terminal": {
392100
392602
  "$type": "RuleCall",
392101
392603
  "rule": {
392102
- "$ref": "#/rules@33"
392604
+ "$ref": "#/rules@37"
392103
392605
  },
392104
392606
  "arguments": []
392105
392607
  }
@@ -392111,7 +392613,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392111
392613
  "terminal": {
392112
392614
  "$type": "RuleCall",
392113
392615
  "rule": {
392114
- "$ref": "#/rules@46"
392616
+ "$ref": "#/rules@50"
392115
392617
  },
392116
392618
  "arguments": []
392117
392619
  }
@@ -392149,7 +392651,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392149
392651
  "terminal": {
392150
392652
  "$type": "RuleCall",
392151
392653
  "rule": {
392152
- "$ref": "#/rules@35"
392654
+ "$ref": "#/rules@39"
392153
392655
  },
392154
392656
  "arguments": []
392155
392657
  }
@@ -392161,7 +392663,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392161
392663
  "terminal": {
392162
392664
  "$type": "RuleCall",
392163
392665
  "rule": {
392164
- "$ref": "#/rules@35"
392666
+ "$ref": "#/rules@39"
392165
392667
  },
392166
392668
  "arguments": []
392167
392669
  },
@@ -392181,7 +392683,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392181
392683
  "terminal": {
392182
392684
  "$type": "RuleCall",
392183
392685
  "rule": {
392184
- "$ref": "#/rules@14"
392686
+ "$ref": "#/rules@16"
392185
392687
  },
392186
392688
  "arguments": []
392187
392689
  }
@@ -392203,7 +392705,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392203
392705
  "terminal": {
392204
392706
  "$type": "RuleCall",
392205
392707
  "rule": {
392206
- "$ref": "#/rules@14"
392708
+ "$ref": "#/rules@16"
392207
392709
  },
392208
392710
  "arguments": []
392209
392711
  }
@@ -392225,7 +392727,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392225
392727
  "terminal": {
392226
392728
  "$type": "RuleCall",
392227
392729
  "rule": {
392228
- "$ref": "#/rules@34"
392730
+ "$ref": "#/rules@38"
392229
392731
  },
392230
392732
  "arguments": []
392231
392733
  },
@@ -392275,7 +392777,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392275
392777
  "terminal": {
392276
392778
  "$type": "RuleCall",
392277
392779
  "rule": {
392278
- "$ref": "#/rules@59"
392780
+ "$ref": "#/rules@35"
392279
392781
  },
392280
392782
  "arguments": []
392281
392783
  }
@@ -392291,7 +392793,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392291
392793
  "terminal": {
392292
392794
  "$type": "RuleCall",
392293
392795
  "rule": {
392294
- "$ref": "#/rules@14"
392796
+ "$ref": "#/rules@16"
392295
392797
  },
392296
392798
  "arguments": []
392297
392799
  }
@@ -392311,7 +392813,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392311
392813
  "terminal": {
392312
392814
  "$type": "RuleCall",
392313
392815
  "rule": {
392314
- "$ref": "#/rules@14"
392816
+ "$ref": "#/rules@16"
392315
392817
  },
392316
392818
  "arguments": []
392317
392819
  }
@@ -392327,7 +392829,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392327
392829
  "terminal": {
392328
392830
  "$type": "RuleCall",
392329
392831
  "rule": {
392330
- "$ref": "#/rules@14"
392832
+ "$ref": "#/rules@16"
392331
392833
  },
392332
392834
  "arguments": []
392333
392835
  }
@@ -392350,7 +392852,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392350
392852
  "terminal": {
392351
392853
  "$type": "RuleCall",
392352
392854
  "rule": {
392353
- "$ref": "#/rules@14"
392855
+ "$ref": "#/rules@16"
392354
392856
  },
392355
392857
  "arguments": []
392356
392858
  }
@@ -392367,6 +392869,28 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392367
392869
  "value": "open"
392368
392870
  },
392369
392871
  "cardinality": "?"
392872
+ },
392873
+ {
392874
+ "$type": "Group",
392875
+ "elements": [
392876
+ {
392877
+ "$type": "Keyword",
392878
+ "value": "direction"
392879
+ },
392880
+ {
392881
+ "$type": "Assignment",
392882
+ "feature": "direction",
392883
+ "operator": "=",
392884
+ "terminal": {
392885
+ "$type": "RuleCall",
392886
+ "rule": {
392887
+ "$ref": "#/rules@39"
392888
+ },
392889
+ "arguments": []
392890
+ }
392891
+ }
392892
+ ],
392893
+ "cardinality": "?"
392370
392894
  }
392371
392895
  ]
392372
392896
  },
@@ -392420,7 +392944,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392420
392944
  "terminal": {
392421
392945
  "$type": "RuleCall",
392422
392946
  "rule": {
392423
- "$ref": "#/rules@59"
392947
+ "$ref": "#/rules@35"
392424
392948
  },
392425
392949
  "arguments": []
392426
392950
  }
@@ -392440,7 +392964,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392440
392964
  "terminal": {
392441
392965
  "$type": "RuleCall",
392442
392966
  "rule": {
392443
- "$ref": "#/rules@14"
392967
+ "$ref": "#/rules@16"
392444
392968
  },
392445
392969
  "arguments": []
392446
392970
  }
@@ -392456,7 +392980,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392456
392980
  "terminal": {
392457
392981
  "$type": "RuleCall",
392458
392982
  "rule": {
392459
- "$ref": "#/rules@14"
392983
+ "$ref": "#/rules@16"
392460
392984
  },
392461
392985
  "arguments": []
392462
392986
  }
@@ -392480,7 +393004,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392480
393004
  "terminal": {
392481
393005
  "$type": "RuleCall",
392482
393006
  "rule": {
392483
- "$ref": "#/rules@14"
393007
+ "$ref": "#/rules@16"
392484
393008
  },
392485
393009
  "arguments": []
392486
393010
  }
@@ -392496,7 +393020,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392496
393020
  "terminal": {
392497
393021
  "$type": "RuleCall",
392498
393022
  "rule": {
392499
- "$ref": "#/rules@14"
393023
+ "$ref": "#/rules@16"
392500
393024
  },
392501
393025
  "arguments": []
392502
393026
  }
@@ -392519,7 +393043,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392519
393043
  "terminal": {
392520
393044
  "$type": "RuleCall",
392521
393045
  "rule": {
392522
- "$ref": "#/rules@14"
393046
+ "$ref": "#/rules@16"
392523
393047
  },
392524
393048
  "arguments": []
392525
393049
  }
@@ -392541,7 +393065,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392541
393065
  "terminal": {
392542
393066
  "$type": "RuleCall",
392543
393067
  "rule": {
392544
- "$ref": "#/rules@14"
393068
+ "$ref": "#/rules@16"
392545
393069
  },
392546
393070
  "arguments": []
392547
393071
  }
@@ -392563,7 +393087,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392563
393087
  "terminal": {
392564
393088
  "$type": "RuleCall",
392565
393089
  "rule": {
392566
- "$ref": "#/rules@35"
393090
+ "$ref": "#/rules@39"
392567
393091
  },
392568
393092
  "arguments": []
392569
393093
  }
@@ -392574,7 +393098,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392574
393098
  {
392575
393099
  "$type": "RuleCall",
392576
393100
  "rule": {
392577
- "$ref": "#/rules@31"
393101
+ "$ref": "#/rules@34"
392578
393102
  },
392579
393103
  "arguments": []
392580
393104
  },
@@ -392592,7 +393116,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392592
393116
  "terminal": {
392593
393117
  "$type": "RuleCall",
392594
393118
  "rule": {
392595
- "$ref": "#/rules@61"
393119
+ "$ref": "#/rules@66"
392596
393120
  },
392597
393121
  "arguments": []
392598
393122
  }
@@ -392614,7 +393138,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392614
393138
  "terminal": {
392615
393139
  "$type": "RuleCall",
392616
393140
  "rule": {
392617
- "$ref": "#/rules@34"
393141
+ "$ref": "#/rules@38"
392618
393142
  },
392619
393143
  "arguments": []
392620
393144
  },
@@ -392650,7 +393174,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392650
393174
  "terminal": {
392651
393175
  "$type": "RuleCall",
392652
393176
  "rule": {
392653
- "$ref": "#/rules@59"
393177
+ "$ref": "#/rules@35"
392654
393178
  },
392655
393179
  "arguments": []
392656
393180
  }
@@ -392670,7 +393194,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392670
393194
  "terminal": {
392671
393195
  "$type": "RuleCall",
392672
393196
  "rule": {
392673
- "$ref": "#/rules@14"
393197
+ "$ref": "#/rules@16"
392674
393198
  },
392675
393199
  "arguments": []
392676
393200
  }
@@ -392686,7 +393210,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392686
393210
  "terminal": {
392687
393211
  "$type": "RuleCall",
392688
393212
  "rule": {
392689
- "$ref": "#/rules@14"
393213
+ "$ref": "#/rules@16"
392690
393214
  },
392691
393215
  "arguments": []
392692
393216
  }
@@ -392704,32 +393228,60 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392704
393228
  "value": "("
392705
393229
  },
392706
393230
  {
392707
- "$type": "Assignment",
392708
- "feature": "w",
392709
- "operator": "=",
392710
- "terminal": {
392711
- "$type": "RuleCall",
392712
- "rule": {
392713
- "$ref": "#/rules@14"
393231
+ "$type": "Alternatives",
393232
+ "elements": [
393233
+ {
393234
+ "$type": "Assignment",
393235
+ "feature": "w_auto",
393236
+ "operator": "?=",
393237
+ "terminal": {
393238
+ "$type": "Keyword",
393239
+ "value": "auto"
393240
+ }
392714
393241
  },
392715
- "arguments": []
392716
- }
393242
+ {
393243
+ "$type": "Assignment",
393244
+ "feature": "w",
393245
+ "operator": "=",
393246
+ "terminal": {
393247
+ "$type": "RuleCall",
393248
+ "rule": {
393249
+ "$ref": "#/rules@16"
393250
+ },
393251
+ "arguments": []
393252
+ }
393253
+ }
393254
+ ]
392717
393255
  },
392718
393256
  {
392719
393257
  "$type": "Keyword",
392720
393258
  "value": ","
392721
393259
  },
392722
393260
  {
392723
- "$type": "Assignment",
392724
- "feature": "l",
392725
- "operator": "=",
392726
- "terminal": {
392727
- "$type": "RuleCall",
392728
- "rule": {
392729
- "$ref": "#/rules@14"
393261
+ "$type": "Alternatives",
393262
+ "elements": [
393263
+ {
393264
+ "$type": "Assignment",
393265
+ "feature": "l_auto",
393266
+ "operator": "?=",
393267
+ "terminal": {
393268
+ "$type": "Keyword",
393269
+ "value": "auto"
393270
+ }
392730
393271
  },
392731
- "arguments": []
392732
- }
393272
+ {
393273
+ "$type": "Assignment",
393274
+ "feature": "l",
393275
+ "operator": "=",
393276
+ "terminal": {
393277
+ "$type": "RuleCall",
393278
+ "rule": {
393279
+ "$ref": "#/rules@16"
393280
+ },
393281
+ "arguments": []
393282
+ }
393283
+ }
393284
+ ]
392733
393285
  },
392734
393286
  {
392735
393287
  "$type": "Keyword",
@@ -392749,7 +393301,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392749
393301
  "terminal": {
392750
393302
  "$type": "RuleCall",
392751
393303
  "rule": {
392752
- "$ref": "#/rules@14"
393304
+ "$ref": "#/rules@16"
392753
393305
  },
392754
393306
  "arguments": []
392755
393307
  }
@@ -392760,7 +393312,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392760
393312
  {
392761
393313
  "$type": "RuleCall",
392762
393314
  "rule": {
392763
- "$ref": "#/rules@31"
393315
+ "$ref": "#/rules@34"
392764
393316
  },
392765
393317
  "arguments": []
392766
393318
  }
@@ -392794,7 +393346,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392794
393346
  "terminal": {
392795
393347
  "$type": "RuleCall",
392796
393348
  "rule": {
392797
- "$ref": "#/rules@61"
393349
+ "$ref": "#/rules@66"
392798
393350
  },
392799
393351
  "arguments": []
392800
393352
  }
@@ -392817,7 +393369,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392817
393369
  "terminal": {
392818
393370
  "$type": "RuleCall",
392819
393371
  "rule": {
392820
- "$ref": "#/rules@14"
393372
+ "$ref": "#/rules@16"
392821
393373
  },
392822
393374
  "arguments": []
392823
393375
  }
@@ -392833,7 +393385,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392833
393385
  "terminal": {
392834
393386
  "$type": "RuleCall",
392835
393387
  "rule": {
392836
- "$ref": "#/rules@14"
393388
+ "$ref": "#/rules@16"
392837
393389
  },
392838
393390
  "arguments": []
392839
393391
  }
@@ -392857,7 +393409,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392857
393409
  "terminal": {
392858
393410
  "$type": "RuleCall",
392859
393411
  "rule": {
392860
- "$ref": "#/rules@14"
393412
+ "$ref": "#/rules@16"
392861
393413
  },
392862
393414
  "arguments": []
392863
393415
  }
@@ -392873,7 +393425,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392873
393425
  "terminal": {
392874
393426
  "$type": "RuleCall",
392875
393427
  "rule": {
392876
- "$ref": "#/rules@14"
393428
+ "$ref": "#/rules@16"
392877
393429
  },
392878
393430
  "arguments": []
392879
393431
  }
@@ -392896,7 +393448,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392896
393448
  "terminal": {
392897
393449
  "$type": "RuleCall",
392898
393450
  "rule": {
392899
- "$ref": "#/rules@14"
393451
+ "$ref": "#/rules@16"
392900
393452
  },
392901
393453
  "arguments": []
392902
393454
  }
@@ -392907,7 +393459,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392907
393459
  {
392908
393460
  "$type": "RuleCall",
392909
393461
  "rule": {
392910
- "$ref": "#/rules@31"
393462
+ "$ref": "#/rules@34"
392911
393463
  },
392912
393464
  "arguments": []
392913
393465
  }
@@ -392941,7 +393493,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392941
393493
  "terminal": {
392942
393494
  "$type": "RuleCall",
392943
393495
  "rule": {
392944
- "$ref": "#/rules@61"
393496
+ "$ref": "#/rules@66"
392945
393497
  },
392946
393498
  "arguments": []
392947
393499
  }
@@ -392964,7 +393516,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392964
393516
  "terminal": {
392965
393517
  "$type": "RuleCall",
392966
393518
  "rule": {
392967
- "$ref": "#/rules@14"
393519
+ "$ref": "#/rules@16"
392968
393520
  },
392969
393521
  "arguments": []
392970
393522
  }
@@ -392980,7 +393532,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
392980
393532
  "terminal": {
392981
393533
  "$type": "RuleCall",
392982
393534
  "rule": {
392983
- "$ref": "#/rules@14"
393535
+ "$ref": "#/rules@16"
392984
393536
  },
392985
393537
  "arguments": []
392986
393538
  }
@@ -393004,7 +393556,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393004
393556
  "terminal": {
393005
393557
  "$type": "RuleCall",
393006
393558
  "rule": {
393007
- "$ref": "#/rules@14"
393559
+ "$ref": "#/rules@16"
393008
393560
  },
393009
393561
  "arguments": []
393010
393562
  }
@@ -393020,7 +393572,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393020
393572
  "terminal": {
393021
393573
  "$type": "RuleCall",
393022
393574
  "rule": {
393023
- "$ref": "#/rules@14"
393575
+ "$ref": "#/rules@16"
393024
393576
  },
393025
393577
  "arguments": []
393026
393578
  }
@@ -393043,7 +393595,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393043
393595
  "terminal": {
393044
393596
  "$type": "RuleCall",
393045
393597
  "rule": {
393046
- "$ref": "#/rules@14"
393598
+ "$ref": "#/rules@16"
393047
393599
  },
393048
393600
  "arguments": []
393049
393601
  }
@@ -393054,7 +393606,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393054
393606
  {
393055
393607
  "$type": "RuleCall",
393056
393608
  "rule": {
393057
- "$ref": "#/rules@31"
393609
+ "$ref": "#/rules@34"
393058
393610
  },
393059
393611
  "arguments": []
393060
393612
  }
@@ -393088,7 +393640,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393088
393640
  "terminal": {
393089
393641
  "$type": "RuleCall",
393090
393642
  "rule": {
393091
- "$ref": "#/rules@61"
393643
+ "$ref": "#/rules@66"
393092
393644
  },
393093
393645
  "arguments": []
393094
393646
  }
@@ -393111,7 +393663,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393111
393663
  "terminal": {
393112
393664
  "$type": "RuleCall",
393113
393665
  "rule": {
393114
- "$ref": "#/rules@14"
393666
+ "$ref": "#/rules@16"
393115
393667
  },
393116
393668
  "arguments": []
393117
393669
  }
@@ -393127,7 +393679,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393127
393679
  "terminal": {
393128
393680
  "$type": "RuleCall",
393129
393681
  "rule": {
393130
- "$ref": "#/rules@14"
393682
+ "$ref": "#/rules@16"
393131
393683
  },
393132
393684
  "arguments": []
393133
393685
  }
@@ -393151,7 +393703,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393151
393703
  "terminal": {
393152
393704
  "$type": "RuleCall",
393153
393705
  "rule": {
393154
- "$ref": "#/rules@14"
393706
+ "$ref": "#/rules@16"
393155
393707
  },
393156
393708
  "arguments": []
393157
393709
  }
@@ -393167,7 +393719,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393167
393719
  "terminal": {
393168
393720
  "$type": "RuleCall",
393169
393721
  "rule": {
393170
- "$ref": "#/rules@14"
393722
+ "$ref": "#/rules@16"
393171
393723
  },
393172
393724
  "arguments": []
393173
393725
  }
@@ -393187,7 +393739,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393187
393739
  "terminal": {
393188
393740
  "$type": "RuleCall",
393189
393741
  "rule": {
393190
- "$ref": "#/rules@14"
393742
+ "$ref": "#/rules@16"
393191
393743
  },
393192
393744
  "arguments": []
393193
393745
  }
@@ -393195,7 +393747,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393195
393747
  {
393196
393748
  "$type": "RuleCall",
393197
393749
  "rule": {
393198
- "$ref": "#/rules@31"
393750
+ "$ref": "#/rules@34"
393199
393751
  },
393200
393752
  "arguments": []
393201
393753
  },
@@ -393213,7 +393765,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393213
393765
  "terminal": {
393214
393766
  "$type": "RuleCall",
393215
393767
  "rule": {
393216
- "$ref": "#/rules@61"
393768
+ "$ref": "#/rules@66"
393217
393769
  },
393218
393770
  "arguments": []
393219
393771
  }
@@ -393251,7 +393803,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393251
393803
  "terminal": {
393252
393804
  "$type": "RuleCall",
393253
393805
  "rule": {
393254
- "$ref": "#/rules@61"
393806
+ "$ref": "#/rules@66"
393255
393807
  },
393256
393808
  "arguments": []
393257
393809
  }
@@ -393274,7 +393826,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393274
393826
  "terminal": {
393275
393827
  "$type": "RuleCall",
393276
393828
  "rule": {
393277
- "$ref": "#/rules@14"
393829
+ "$ref": "#/rules@16"
393278
393830
  },
393279
393831
  "arguments": []
393280
393832
  }
@@ -393290,7 +393842,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393290
393842
  "terminal": {
393291
393843
  "$type": "RuleCall",
393292
393844
  "rule": {
393293
- "$ref": "#/rules@14"
393845
+ "$ref": "#/rules@16"
393294
393846
  },
393295
393847
  "arguments": []
393296
393848
  }
@@ -393314,7 +393866,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393314
393866
  "terminal": {
393315
393867
  "$type": "RuleCall",
393316
393868
  "rule": {
393317
- "$ref": "#/rules@14"
393869
+ "$ref": "#/rules@16"
393318
393870
  },
393319
393871
  "arguments": []
393320
393872
  }
@@ -393330,7 +393882,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393330
393882
  "terminal": {
393331
393883
  "$type": "RuleCall",
393332
393884
  "rule": {
393333
- "$ref": "#/rules@14"
393885
+ "$ref": "#/rules@16"
393334
393886
  },
393335
393887
  "arguments": []
393336
393888
  }
@@ -393353,7 +393905,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393353
393905
  "terminal": {
393354
393906
  "$type": "RuleCall",
393355
393907
  "rule": {
393356
- "$ref": "#/rules@14"
393908
+ "$ref": "#/rules@16"
393357
393909
  },
393358
393910
  "arguments": []
393359
393911
  }
@@ -393364,7 +393916,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393364
393916
  {
393365
393917
  "$type": "RuleCall",
393366
393918
  "rule": {
393367
- "$ref": "#/rules@31"
393919
+ "$ref": "#/rules@34"
393368
393920
  },
393369
393921
  "arguments": []
393370
393922
  },
@@ -393382,7 +393934,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393382
393934
  "terminal": {
393383
393935
  "$type": "RuleCall",
393384
393936
  "rule": {
393385
- "$ref": "#/rules@61"
393937
+ "$ref": "#/rules@66"
393386
393938
  },
393387
393939
  "arguments": []
393388
393940
  }
@@ -393420,7 +393972,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393420
393972
  "terminal": {
393421
393973
  "$type": "RuleCall",
393422
393974
  "rule": {
393423
- "$ref": "#/rules@61"
393975
+ "$ref": "#/rules@66"
393424
393976
  },
393425
393977
  "arguments": []
393426
393978
  }
@@ -393443,7 +393995,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393443
393995
  "terminal": {
393444
393996
  "$type": "RuleCall",
393445
393997
  "rule": {
393446
- "$ref": "#/rules@14"
393998
+ "$ref": "#/rules@16"
393447
393999
  },
393448
394000
  "arguments": []
393449
394001
  }
@@ -393459,7 +394011,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393459
394011
  "terminal": {
393460
394012
  "$type": "RuleCall",
393461
394013
  "rule": {
393462
- "$ref": "#/rules@14"
394014
+ "$ref": "#/rules@16"
393463
394015
  },
393464
394016
  "arguments": []
393465
394017
  }
@@ -393483,7 +394035,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393483
394035
  "terminal": {
393484
394036
  "$type": "RuleCall",
393485
394037
  "rule": {
393486
- "$ref": "#/rules@14"
394038
+ "$ref": "#/rules@16"
393487
394039
  },
393488
394040
  "arguments": []
393489
394041
  }
@@ -393499,7 +394051,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393499
394051
  "terminal": {
393500
394052
  "$type": "RuleCall",
393501
394053
  "rule": {
393502
- "$ref": "#/rules@14"
394054
+ "$ref": "#/rules@16"
393503
394055
  },
393504
394056
  "arguments": []
393505
394057
  }
@@ -393515,7 +394067,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393515
394067
  "terminal": {
393516
394068
  "$type": "RuleCall",
393517
394069
  "rule": {
393518
- "$ref": "#/rules@14"
394070
+ "$ref": "#/rules@16"
393519
394071
  },
393520
394072
  "arguments": []
393521
394073
  }
@@ -393535,7 +394087,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393535
394087
  "terminal": {
393536
394088
  "$type": "RuleCall",
393537
394089
  "rule": {
393538
- "$ref": "#/rules@35"
394090
+ "$ref": "#/rules@39"
393539
394091
  },
393540
394092
  "arguments": []
393541
394093
  }
@@ -393554,7 +394106,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393554
394106
  "terminal": {
393555
394107
  "$type": "RuleCall",
393556
394108
  "rule": {
393557
- "$ref": "#/rules@14"
394109
+ "$ref": "#/rules@16"
393558
394110
  },
393559
394111
  "arguments": []
393560
394112
  }
@@ -393576,7 +394128,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393576
394128
  "terminal": {
393577
394129
  "$type": "RuleCall",
393578
394130
  "rule": {
393579
- "$ref": "#/rules@14"
394131
+ "$ref": "#/rules@16"
393580
394132
  },
393581
394133
  "arguments": []
393582
394134
  }
@@ -393598,7 +394150,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393598
394150
  "terminal": {
393599
394151
  "$type": "RuleCall",
393600
394152
  "rule": {
393601
- "$ref": "#/rules@14"
394153
+ "$ref": "#/rules@16"
393602
394154
  },
393603
394155
  "arguments": []
393604
394156
  }
@@ -393620,7 +394172,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393620
394172
  "terminal": {
393621
394173
  "$type": "RuleCall",
393622
394174
  "rule": {
393623
- "$ref": "#/rules@14"
394175
+ "$ref": "#/rules@16"
393624
394176
  },
393625
394177
  "arguments": []
393626
394178
  }
@@ -393670,7 +394222,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393670
394222
  "terminal": {
393671
394223
  "$type": "RuleCall",
393672
394224
  "rule": {
393673
- "$ref": "#/rules@14"
394225
+ "$ref": "#/rules@16"
393674
394226
  },
393675
394227
  "arguments": []
393676
394228
  }
@@ -393681,7 +394233,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393681
394233
  {
393682
394234
  "$type": "RuleCall",
393683
394235
  "rule": {
393684
- "$ref": "#/rules@31"
394236
+ "$ref": "#/rules@34"
393685
394237
  },
393686
394238
  "arguments": []
393687
394239
  },
@@ -393699,7 +394251,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393699
394251
  "terminal": {
393700
394252
  "$type": "RuleCall",
393701
394253
  "rule": {
393702
- "$ref": "#/rules@61"
394254
+ "$ref": "#/rules@66"
393703
394255
  },
393704
394256
  "arguments": []
393705
394257
  }
@@ -393737,7 +394289,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393737
394289
  "terminal": {
393738
394290
  "$type": "RuleCall",
393739
394291
  "rule": {
393740
- "$ref": "#/rules@61"
394292
+ "$ref": "#/rules@66"
393741
394293
  },
393742
394294
  "arguments": []
393743
394295
  }
@@ -393760,7 +394312,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393760
394312
  "terminal": {
393761
394313
  "$type": "RuleCall",
393762
394314
  "rule": {
393763
- "$ref": "#/rules@44"
394315
+ "$ref": "#/rules@48"
393764
394316
  },
393765
394317
  "arguments": []
393766
394318
  }
@@ -393779,7 +394331,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393779
394331
  "terminal": {
393780
394332
  "$type": "RuleCall",
393781
394333
  "rule": {
393782
- "$ref": "#/rules@44"
394334
+ "$ref": "#/rules@48"
393783
394335
  },
393784
394336
  "arguments": []
393785
394337
  }
@@ -393824,7 +394376,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393824
394376
  "terminal": {
393825
394377
  "$type": "RuleCall",
393826
394378
  "rule": {
393827
- "$ref": "#/rules@14"
394379
+ "$ref": "#/rules@16"
393828
394380
  },
393829
394381
  "arguments": []
393830
394382
  }
@@ -393840,7 +394392,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393840
394392
  "terminal": {
393841
394393
  "$type": "RuleCall",
393842
394394
  "rule": {
393843
- "$ref": "#/rules@14"
394395
+ "$ref": "#/rules@16"
393844
394396
  },
393845
394397
  "arguments": []
393846
394398
  }
@@ -393859,7 +394411,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393859
394411
  "terminal": {
393860
394412
  "$type": "RuleCall",
393861
394413
  "rule": {
393862
- "$ref": "#/rules@14"
394414
+ "$ref": "#/rules@16"
393863
394415
  },
393864
394416
  "arguments": []
393865
394417
  }
@@ -393870,7 +394422,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393870
394422
  {
393871
394423
  "$type": "RuleCall",
393872
394424
  "rule": {
393873
- "$ref": "#/rules@31"
394425
+ "$ref": "#/rules@34"
393874
394426
  },
393875
394427
  "arguments": []
393876
394428
  },
@@ -393888,7 +394440,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393888
394440
  "terminal": {
393889
394441
  "$type": "RuleCall",
393890
394442
  "rule": {
393891
- "$ref": "#/rules@61"
394443
+ "$ref": "#/rules@66"
393892
394444
  },
393893
394445
  "arguments": []
393894
394446
  }
@@ -393919,7 +394471,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393919
394471
  "terminal": {
393920
394472
  "$type": "RuleCall",
393921
394473
  "rule": {
393922
- "$ref": "#/rules@60"
394474
+ "$ref": "#/rules@65"
393923
394475
  },
393924
394476
  "arguments": []
393925
394477
  }
@@ -393935,7 +394487,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393935
394487
  "terminal": {
393936
394488
  "$type": "RuleCall",
393937
394489
  "rule": {
393938
- "$ref": "#/rules@60"
394490
+ "$ref": "#/rules@65"
393939
394491
  },
393940
394492
  "arguments": []
393941
394493
  }
@@ -393974,7 +394526,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393974
394526
  "terminal": {
393975
394527
  "$type": "RuleCall",
393976
394528
  "rule": {
393977
- "$ref": "#/rules@61"
394529
+ "$ref": "#/rules@66"
393978
394530
  },
393979
394531
  "arguments": []
393980
394532
  }
@@ -393990,11 +394542,19 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
393990
394542
  "feature": "assetRef",
393991
394543
  "operator": "=",
393992
394544
  "terminal": {
393993
- "$type": "RuleCall",
393994
- "rule": {
393995
- "$ref": "#/rules@47"
394545
+ "$type": "CrossReference",
394546
+ "type": {
394547
+ "$ref": "#/rules@2"
393996
394548
  },
393997
- "arguments": []
394549
+ "terminal": {
394550
+ "$type": "RuleCall",
394551
+ "rule": {
394552
+ "$ref": "#/rules@51"
394553
+ },
394554
+ "arguments": []
394555
+ },
394556
+ "deprecatedSyntax": false,
394557
+ "isMulti": false
393998
394558
  }
393999
394559
  },
394000
394560
  {
@@ -394011,7 +394571,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394011
394571
  "terminal": {
394012
394572
  "$type": "RuleCall",
394013
394573
  "rule": {
394014
- "$ref": "#/rules@48"
394574
+ "$ref": "#/rules@52"
394015
394575
  },
394016
394576
  "arguments": []
394017
394577
  }
@@ -394035,7 +394595,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394035
394595
  "terminal": {
394036
394596
  "$type": "RuleCall",
394037
394597
  "rule": {
394038
- "$ref": "#/rules@14"
394598
+ "$ref": "#/rules@16"
394039
394599
  },
394040
394600
  "arguments": []
394041
394601
  }
@@ -394051,7 +394611,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394051
394611
  "terminal": {
394052
394612
  "$type": "RuleCall",
394053
394613
  "rule": {
394054
- "$ref": "#/rules@14"
394614
+ "$ref": "#/rules@16"
394055
394615
  },
394056
394616
  "arguments": []
394057
394617
  }
@@ -394074,7 +394634,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394074
394634
  "terminal": {
394075
394635
  "$type": "RuleCall",
394076
394636
  "rule": {
394077
- "$ref": "#/rules@14"
394637
+ "$ref": "#/rules@16"
394078
394638
  },
394079
394639
  "arguments": []
394080
394640
  }
@@ -394096,7 +394656,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394096
394656
  "terminal": {
394097
394657
  "$type": "RuleCall",
394098
394658
  "rule": {
394099
- "$ref": "#/rules@14"
394659
+ "$ref": "#/rules@16"
394100
394660
  },
394101
394661
  "arguments": []
394102
394662
  }
@@ -394118,7 +394678,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394118
394678
  "terminal": {
394119
394679
  "$type": "RuleCall",
394120
394680
  "rule": {
394121
- "$ref": "#/rules@61"
394681
+ "$ref": "#/rules@66"
394122
394682
  },
394123
394683
  "arguments": []
394124
394684
  }
@@ -394140,7 +394700,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394140
394700
  "terminal": {
394141
394701
  "$type": "RuleCall",
394142
394702
  "rule": {
394143
- "$ref": "#/rules@49"
394703
+ "$ref": "#/rules@53"
394144
394704
  },
394145
394705
  "arguments": []
394146
394706
  }
@@ -394166,7 +394726,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394166
394726
  "terminal": {
394167
394727
  "$type": "RuleCall",
394168
394728
  "rule": {
394169
- "$ref": "#/rules@14"
394729
+ "$ref": "#/rules@16"
394170
394730
  },
394171
394731
  "arguments": []
394172
394732
  }
@@ -394182,7 +394742,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394182
394742
  "terminal": {
394183
394743
  "$type": "RuleCall",
394184
394744
  "rule": {
394185
- "$ref": "#/rules@14"
394745
+ "$ref": "#/rules@16"
394186
394746
  },
394187
394747
  "arguments": []
394188
394748
  }
@@ -394197,7 +394757,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394197
394757
  {
394198
394758
  "$type": "RuleCall",
394199
394759
  "rule": {
394200
- "$ref": "#/rules@31"
394760
+ "$ref": "#/rules@34"
394201
394761
  },
394202
394762
  "arguments": []
394203
394763
  }
@@ -394231,7 +394791,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394231
394791
  "terminal": {
394232
394792
  "$type": "RuleCall",
394233
394793
  "rule": {
394234
- "$ref": "#/rules@61"
394794
+ "$ref": "#/rules@66"
394235
394795
  },
394236
394796
  "arguments": []
394237
394797
  }
@@ -394247,11 +394807,19 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394247
394807
  "feature": "assetRef",
394248
394808
  "operator": "=",
394249
394809
  "terminal": {
394250
- "$type": "RuleCall",
394251
- "rule": {
394252
- "$ref": "#/rules@47"
394810
+ "$type": "CrossReference",
394811
+ "type": {
394812
+ "$ref": "#/rules@2"
394253
394813
  },
394254
- "arguments": []
394814
+ "terminal": {
394815
+ "$type": "RuleCall",
394816
+ "rule": {
394817
+ "$ref": "#/rules@51"
394818
+ },
394819
+ "arguments": []
394820
+ },
394821
+ "deprecatedSyntax": false,
394822
+ "isMulti": false
394255
394823
  }
394256
394824
  },
394257
394825
  {
@@ -394268,7 +394836,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394268
394836
  "terminal": {
394269
394837
  "$type": "RuleCall",
394270
394838
  "rule": {
394271
- "$ref": "#/rules@48"
394839
+ "$ref": "#/rules@52"
394272
394840
  },
394273
394841
  "arguments": []
394274
394842
  }
@@ -394291,7 +394859,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394291
394859
  "terminal": {
394292
394860
  "$type": "RuleCall",
394293
394861
  "rule": {
394294
- "$ref": "#/rules@49"
394862
+ "$ref": "#/rules@53"
394295
394863
  },
394296
394864
  "arguments": []
394297
394865
  }
@@ -394317,7 +394885,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394317
394885
  "terminal": {
394318
394886
  "$type": "RuleCall",
394319
394887
  "rule": {
394320
- "$ref": "#/rules@14"
394888
+ "$ref": "#/rules@16"
394321
394889
  },
394322
394890
  "arguments": []
394323
394891
  }
@@ -394333,7 +394901,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394333
394901
  "terminal": {
394334
394902
  "$type": "RuleCall",
394335
394903
  "rule": {
394336
- "$ref": "#/rules@14"
394904
+ "$ref": "#/rules@16"
394337
394905
  },
394338
394906
  "arguments": []
394339
394907
  }
@@ -394359,7 +394927,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394359
394927
  "terminal": {
394360
394928
  "$type": "RuleCall",
394361
394929
  "rule": {
394362
- "$ref": "#/rules@14"
394930
+ "$ref": "#/rules@16"
394363
394931
  },
394364
394932
  "arguments": []
394365
394933
  }
@@ -394381,7 +394949,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394381
394949
  "terminal": {
394382
394950
  "$type": "RuleCall",
394383
394951
  "rule": {
394384
- "$ref": "#/rules@14"
394952
+ "$ref": "#/rules@16"
394385
394953
  },
394386
394954
  "arguments": []
394387
394955
  }
@@ -394392,7 +394960,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394392
394960
  {
394393
394961
  "$type": "RuleCall",
394394
394962
  "rule": {
394395
- "$ref": "#/rules@31"
394963
+ "$ref": "#/rules@34"
394396
394964
  },
394397
394965
  "arguments": []
394398
394966
  }
@@ -394404,7 +394972,8 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394404
394972
  },
394405
394973
  {
394406
394974
  "$type": "ParserRule",
394407
- "name": "AssetRef",
394975
+ "name": "AssetName",
394976
+ "dataType": "string",
394408
394977
  "definition": {
394409
394978
  "$type": "Group",
394410
394979
  "elements": [
@@ -394412,16 +394981,11 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394412
394981
  "$type": "Group",
394413
394982
  "elements": [
394414
394983
  {
394415
- "$type": "Assignment",
394416
- "feature": "ns",
394417
- "operator": "=",
394418
- "terminal": {
394419
- "$type": "RuleCall",
394420
- "rule": {
394421
- "$ref": "#/rules@59"
394422
- },
394423
- "arguments": []
394424
- }
394984
+ "$type": "RuleCall",
394985
+ "rule": {
394986
+ "$ref": "#/rules@64"
394987
+ },
394988
+ "arguments": []
394425
394989
  },
394426
394990
  {
394427
394991
  "$type": "Keyword",
@@ -394431,16 +394995,11 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394431
394995
  "cardinality": "?"
394432
394996
  },
394433
394997
  {
394434
- "$type": "Assignment",
394435
- "feature": "id",
394436
- "operator": "=",
394437
- "terminal": {
394438
- "$type": "RuleCall",
394439
- "rule": {
394440
- "$ref": "#/rules@61"
394441
- },
394442
- "arguments": []
394443
- }
394998
+ "$type": "RuleCall",
394999
+ "rule": {
395000
+ "$ref": "#/rules@66"
395001
+ },
395002
+ "arguments": []
394444
395003
  }
394445
395004
  ]
394446
395005
  },
@@ -394469,7 +395028,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394469
395028
  "terminal": {
394470
395029
  "$type": "RuleCall",
394471
395030
  "rule": {
394472
- "$ref": "#/rules@61"
395031
+ "$ref": "#/rules@66"
394473
395032
  },
394474
395033
  "arguments": []
394475
395034
  }
@@ -394485,7 +395044,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394485
395044
  "terminal": {
394486
395045
  "$type": "RuleCall",
394487
395046
  "rule": {
394488
- "$ref": "#/rules@61"
395047
+ "$ref": "#/rules@66"
394489
395048
  },
394490
395049
  "arguments": []
394491
395050
  }
@@ -394505,7 +395064,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394505
395064
  "terminal": {
394506
395065
  "$type": "RuleCall",
394507
395066
  "rule": {
394508
- "$ref": "#/rules@60"
395067
+ "$ref": "#/rules@65"
394509
395068
  },
394510
395069
  "arguments": []
394511
395070
  }
@@ -394521,7 +395080,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394521
395080
  "terminal": {
394522
395081
  "$type": "RuleCall",
394523
395082
  "rule": {
394524
- "$ref": "#/rules@60"
395083
+ "$ref": "#/rules@65"
394525
395084
  },
394526
395085
  "arguments": []
394527
395086
  }
@@ -394537,7 +395096,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394537
395096
  "terminal": {
394538
395097
  "$type": "RuleCall",
394539
395098
  "rule": {
394540
- "$ref": "#/rules@60"
395099
+ "$ref": "#/rules@65"
394541
395100
  },
394542
395101
  "arguments": []
394543
395102
  }
@@ -394560,7 +395119,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394560
395119
  "terminal": {
394561
395120
  "$type": "RuleCall",
394562
395121
  "rule": {
394563
- "$ref": "#/rules@61"
395122
+ "$ref": "#/rules@66"
394564
395123
  },
394565
395124
  "arguments": []
394566
395125
  }
@@ -394582,7 +395141,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394582
395141
  "terminal": {
394583
395142
  "$type": "RuleCall",
394584
395143
  "rule": {
394585
- "$ref": "#/rules@61"
395144
+ "$ref": "#/rules@66"
394586
395145
  },
394587
395146
  "arguments": []
394588
395147
  }
@@ -394659,38 +395218,24 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394659
395218
  "$type": "Keyword",
394660
395219
  "value": "use"
394661
395220
  },
394662
- {
394663
- "$type": "Group",
394664
- "elements": [
394665
- {
394666
- "$type": "Assignment",
394667
- "feature": "ns",
394668
- "operator": "=",
394669
- "terminal": {
394670
- "$type": "RuleCall",
394671
- "rule": {
394672
- "$ref": "#/rules@59"
394673
- },
394674
- "arguments": []
394675
- }
394676
- },
394677
- {
394678
- "$type": "Keyword",
394679
- "value": "."
394680
- }
394681
- ],
394682
- "cardinality": "?"
394683
- },
394684
395221
  {
394685
395222
  "$type": "Assignment",
394686
- "feature": "ref",
395223
+ "feature": "target",
394687
395224
  "operator": "=",
394688
395225
  "terminal": {
394689
- "$type": "RuleCall",
394690
- "rule": {
394691
- "$ref": "#/rules@59"
395226
+ "$type": "CrossReference",
395227
+ "type": {
395228
+ "$ref": "#/rules@30"
394692
395229
  },
394693
- "arguments": []
395230
+ "terminal": {
395231
+ "$type": "RuleCall",
395232
+ "rule": {
395233
+ "$ref": "#/rules@56"
395234
+ },
395235
+ "arguments": []
395236
+ },
395237
+ "deprecatedSyntax": false,
395238
+ "isMulti": false
394694
395239
  }
394695
395240
  },
394696
395241
  {
@@ -394707,7 +395252,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394707
395252
  "terminal": {
394708
395253
  "$type": "RuleCall",
394709
395254
  "rule": {
394710
- "$ref": "#/rules@61"
395255
+ "$ref": "#/rules@66"
394711
395256
  },
394712
395257
  "arguments": []
394713
395258
  }
@@ -394730,7 +395275,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394730
395275
  "terminal": {
394731
395276
  "$type": "RuleCall",
394732
395277
  "rule": {
394733
- "$ref": "#/rules@14"
395278
+ "$ref": "#/rules@16"
394734
395279
  },
394735
395280
  "arguments": []
394736
395281
  }
@@ -394746,7 +395291,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394746
395291
  "terminal": {
394747
395292
  "$type": "RuleCall",
394748
395293
  "rule": {
394749
- "$ref": "#/rules@14"
395294
+ "$ref": "#/rules@16"
394750
395295
  },
394751
395296
  "arguments": []
394752
395297
  }
@@ -394755,6 +395300,28 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394755
395300
  "$type": "Keyword",
394756
395301
  "value": ")"
394757
395302
  },
395303
+ {
395304
+ "$type": "Group",
395305
+ "elements": [
395306
+ {
395307
+ "$type": "Keyword",
395308
+ "value": "rotation"
395309
+ },
395310
+ {
395311
+ "$type": "Assignment",
395312
+ "feature": "rotation",
395313
+ "operator": "=",
395314
+ "terminal": {
395315
+ "$type": "RuleCall",
395316
+ "rule": {
395317
+ "$ref": "#/rules@16"
395318
+ },
395319
+ "arguments": []
395320
+ }
395321
+ }
395322
+ ],
395323
+ "cardinality": "?"
395324
+ },
394758
395325
  {
394759
395326
  "$type": "Group",
394760
395327
  "elements": [
@@ -394773,7 +395340,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394773
395340
  "terminal": {
394774
395341
  "$type": "RuleCall",
394775
395342
  "rule": {
394776
- "$ref": "#/rules@51"
395343
+ "$ref": "#/rules@55"
394777
395344
  },
394778
395345
  "arguments": []
394779
395346
  }
@@ -394792,7 +395359,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394792
395359
  "terminal": {
394793
395360
  "$type": "RuleCall",
394794
395361
  "rule": {
394795
- "$ref": "#/rules@51"
395362
+ "$ref": "#/rules@55"
394796
395363
  },
394797
395364
  "arguments": []
394798
395365
  }
@@ -394810,7 +395377,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394810
395377
  {
394811
395378
  "$type": "RuleCall",
394812
395379
  "rule": {
394813
- "$ref": "#/rules@31"
395380
+ "$ref": "#/rules@34"
394814
395381
  },
394815
395382
  "arguments": []
394816
395383
  }
@@ -394833,7 +395400,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394833
395400
  "terminal": {
394834
395401
  "$type": "RuleCall",
394835
395402
  "rule": {
394836
- "$ref": "#/rules@59"
395403
+ "$ref": "#/rules@64"
394837
395404
  },
394838
395405
  "arguments": []
394839
395406
  }
@@ -394849,7 +395416,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394849
395416
  "terminal": {
394850
395417
  "$type": "RuleCall",
394851
395418
  "rule": {
394852
- "$ref": "#/rules@14"
395419
+ "$ref": "#/rules@16"
394853
395420
  },
394854
395421
  "arguments": []
394855
395422
  }
@@ -394860,6 +395427,43 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394860
395427
  "fragment": false,
394861
395428
  "parameters": []
394862
395429
  },
395430
+ {
395431
+ "$type": "ParserRule",
395432
+ "name": "QualifiedName",
395433
+ "dataType": "string",
395434
+ "definition": {
395435
+ "$type": "Group",
395436
+ "elements": [
395437
+ {
395438
+ "$type": "RuleCall",
395439
+ "rule": {
395440
+ "$ref": "#/rules@64"
395441
+ },
395442
+ "arguments": []
395443
+ },
395444
+ {
395445
+ "$type": "Group",
395446
+ "elements": [
395447
+ {
395448
+ "$type": "Keyword",
395449
+ "value": "."
395450
+ },
395451
+ {
395452
+ "$type": "RuleCall",
395453
+ "rule": {
395454
+ "$ref": "#/rules@64"
395455
+ },
395456
+ "arguments": []
395457
+ }
395458
+ ],
395459
+ "cardinality": "*"
395460
+ }
395461
+ ]
395462
+ },
395463
+ "entry": false,
395464
+ "fragment": false,
395465
+ "parameters": []
395466
+ },
394863
395467
  {
394864
395468
  "$type": "ParserRule",
394865
395469
  "name": "Roof",
@@ -394884,7 +395488,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394884
395488
  "terminal": {
394885
395489
  "$type": "RuleCall",
394886
395490
  "rule": {
394887
- "$ref": "#/rules@61"
395491
+ "$ref": "#/rules@66"
394888
395492
  },
394889
395493
  "arguments": []
394890
395494
  }
@@ -394949,7 +395553,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394949
395553
  "terminal": {
394950
395554
  "$type": "RuleCall",
394951
395555
  "rule": {
394952
- "$ref": "#/rules@53"
395556
+ "$ref": "#/rules@58"
394953
395557
  },
394954
395558
  "arguments": []
394955
395559
  },
@@ -394969,7 +395573,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394969
395573
  "terminal": {
394970
395574
  "$type": "RuleCall",
394971
395575
  "rule": {
394972
- "$ref": "#/rules@14"
395576
+ "$ref": "#/rules@16"
394973
395577
  },
394974
395578
  "arguments": []
394975
395579
  }
@@ -394991,7 +395595,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
394991
395595
  "terminal": {
394992
395596
  "$type": "RuleCall",
394993
395597
  "rule": {
394994
- "$ref": "#/rules@14"
395598
+ "$ref": "#/rules@16"
394995
395599
  },
394996
395600
  "arguments": []
394997
395601
  }
@@ -395013,7 +395617,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395013
395617
  "terminal": {
395014
395618
  "$type": "RuleCall",
395015
395619
  "rule": {
395016
- "$ref": "#/rules@14"
395620
+ "$ref": "#/rules@16"
395017
395621
  },
395018
395622
  "arguments": []
395019
395623
  }
@@ -395029,7 +395633,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395029
395633
  "terminal": {
395030
395634
  "$type": "RuleCall",
395031
395635
  "rule": {
395032
- "$ref": "#/rules@14"
395636
+ "$ref": "#/rules@16"
395033
395637
  },
395034
395638
  "arguments": []
395035
395639
  }
@@ -395051,7 +395655,29 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395051
395655
  "terminal": {
395052
395656
  "$type": "RuleCall",
395053
395657
  "rule": {
395054
- "$ref": "#/rules@14"
395658
+ "$ref": "#/rules@16"
395659
+ },
395660
+ "arguments": []
395661
+ }
395662
+ }
395663
+ ],
395664
+ "cardinality": "?"
395665
+ },
395666
+ {
395667
+ "$type": "Group",
395668
+ "elements": [
395669
+ {
395670
+ "$type": "Keyword",
395671
+ "value": "framing"
395672
+ },
395673
+ {
395674
+ "$type": "Assignment",
395675
+ "feature": "framing",
395676
+ "operator": "=",
395677
+ "terminal": {
395678
+ "$type": "RuleCall",
395679
+ "rule": {
395680
+ "$ref": "#/rules@23"
395055
395681
  },
395056
395682
  "arguments": []
395057
395683
  }
@@ -395062,7 +395688,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395062
395688
  {
395063
395689
  "$type": "RuleCall",
395064
395690
  "rule": {
395065
- "$ref": "#/rules@31"
395691
+ "$ref": "#/rules@34"
395066
395692
  },
395067
395693
  "arguments": []
395068
395694
  },
@@ -395080,7 +395706,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395080
395706
  "terminal": {
395081
395707
  "$type": "RuleCall",
395082
395708
  "rule": {
395083
- "$ref": "#/rules@61"
395709
+ "$ref": "#/rules@66"
395084
395710
  },
395085
395711
  "arguments": []
395086
395712
  }
@@ -395102,7 +395728,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395102
395728
  "terminal": {
395103
395729
  "$type": "RuleCall",
395104
395730
  "rule": {
395105
- "$ref": "#/rules@54"
395731
+ "$ref": "#/rules@59"
395106
395732
  },
395107
395733
  "arguments": []
395108
395734
  }
@@ -395114,7 +395740,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395114
395740
  "terminal": {
395115
395741
  "$type": "RuleCall",
395116
395742
  "rule": {
395117
- "$ref": "#/rules@55"
395743
+ "$ref": "#/rules@60"
395118
395744
  },
395119
395745
  "arguments": []
395120
395746
  }
@@ -395143,34 +395769,97 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395143
395769
  "value": "slope"
395144
395770
  },
395145
395771
  {
395146
- "$type": "Assignment",
395147
- "feature": "by",
395148
- "operator": "=",
395149
- "terminal": {
395150
- "$type": "Alternatives",
395151
- "elements": [
395152
- {
395153
- "$type": "Keyword",
395154
- "value": "angle"
395155
- },
395156
- {
395157
- "$type": "Keyword",
395158
- "value": "height"
395159
- }
395160
- ]
395161
- }
395162
- },
395163
- {
395164
- "$type": "Assignment",
395165
- "feature": "value",
395166
- "operator": "=",
395167
- "terminal": {
395168
- "$type": "RuleCall",
395169
- "rule": {
395170
- "$ref": "#/rules@14"
395772
+ "$type": "Alternatives",
395773
+ "elements": [
395774
+ {
395775
+ "$type": "Group",
395776
+ "elements": [
395777
+ {
395778
+ "$type": "Keyword",
395779
+ "value": "angle"
395780
+ },
395781
+ {
395782
+ "$type": "Alternatives",
395783
+ "elements": [
395784
+ {
395785
+ "$type": "Group",
395786
+ "elements": [
395787
+ {
395788
+ "$type": "Keyword",
395789
+ "value": "("
395790
+ },
395791
+ {
395792
+ "$type": "Assignment",
395793
+ "feature": "angle_left",
395794
+ "operator": "=",
395795
+ "terminal": {
395796
+ "$type": "RuleCall",
395797
+ "rule": {
395798
+ "$ref": "#/rules@16"
395799
+ },
395800
+ "arguments": []
395801
+ }
395802
+ },
395803
+ {
395804
+ "$type": "Keyword",
395805
+ "value": ","
395806
+ },
395807
+ {
395808
+ "$type": "Assignment",
395809
+ "feature": "angle_right",
395810
+ "operator": "=",
395811
+ "terminal": {
395812
+ "$type": "RuleCall",
395813
+ "rule": {
395814
+ "$ref": "#/rules@16"
395815
+ },
395816
+ "arguments": []
395817
+ }
395818
+ },
395819
+ {
395820
+ "$type": "Keyword",
395821
+ "value": ")"
395822
+ }
395823
+ ]
395824
+ },
395825
+ {
395826
+ "$type": "Assignment",
395827
+ "feature": "angle_deg",
395828
+ "operator": "=",
395829
+ "terminal": {
395830
+ "$type": "RuleCall",
395831
+ "rule": {
395832
+ "$ref": "#/rules@16"
395833
+ },
395834
+ "arguments": []
395835
+ }
395836
+ }
395837
+ ]
395838
+ }
395839
+ ]
395171
395840
  },
395172
- "arguments": []
395173
- }
395841
+ {
395842
+ "$type": "Group",
395843
+ "elements": [
395844
+ {
395845
+ "$type": "Keyword",
395846
+ "value": "height"
395847
+ },
395848
+ {
395849
+ "$type": "Assignment",
395850
+ "feature": "ridge_h",
395851
+ "operator": "=",
395852
+ "terminal": {
395853
+ "$type": "RuleCall",
395854
+ "rule": {
395855
+ "$ref": "#/rules@16"
395856
+ },
395857
+ "arguments": []
395858
+ }
395859
+ }
395860
+ ]
395861
+ }
395862
+ ]
395174
395863
  }
395175
395864
  ]
395176
395865
  },
@@ -395195,7 +395884,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395195
395884
  "terminal": {
395196
395885
  "$type": "RuleCall",
395197
395886
  "rule": {
395198
- "$ref": "#/rules@61"
395887
+ "$ref": "#/rules@66"
395199
395888
  },
395200
395889
  "arguments": []
395201
395890
  }
@@ -395215,7 +395904,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395215
395904
  "terminal": {
395216
395905
  "$type": "RuleCall",
395217
395906
  "rule": {
395218
- "$ref": "#/rules@14"
395907
+ "$ref": "#/rules@16"
395219
395908
  },
395220
395909
  "arguments": []
395221
395910
  }
@@ -395231,7 +395920,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395231
395920
  "terminal": {
395232
395921
  "$type": "RuleCall",
395233
395922
  "rule": {
395234
- "$ref": "#/rules@14"
395923
+ "$ref": "#/rules@16"
395235
395924
  },
395236
395925
  "arguments": []
395237
395926
  }
@@ -395255,7 +395944,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395255
395944
  "terminal": {
395256
395945
  "$type": "RuleCall",
395257
395946
  "rule": {
395258
- "$ref": "#/rules@14"
395947
+ "$ref": "#/rules@16"
395259
395948
  },
395260
395949
  "arguments": []
395261
395950
  }
@@ -395271,7 +395960,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395271
395960
  "terminal": {
395272
395961
  "$type": "RuleCall",
395273
395962
  "rule": {
395274
- "$ref": "#/rules@14"
395963
+ "$ref": "#/rules@16"
395275
395964
  },
395276
395965
  "arguments": []
395277
395966
  }
@@ -395291,7 +395980,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395291
395980
  "terminal": {
395292
395981
  "$type": "RuleCall",
395293
395982
  "rule": {
395294
- "$ref": "#/rules@14"
395983
+ "$ref": "#/rules@16"
395295
395984
  },
395296
395985
  "arguments": []
395297
395986
  }
@@ -395398,7 +396087,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395398
396087
  "terminal": {
395399
396088
  "$type": "RuleCall",
395400
396089
  "rule": {
395401
- "$ref": "#/rules@14"
396090
+ "$ref": "#/rules@16"
395402
396091
  },
395403
396092
  "arguments": []
395404
396093
  }
@@ -395414,7 +396103,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395414
396103
  "terminal": {
395415
396104
  "$type": "RuleCall",
395416
396105
  "rule": {
395417
- "$ref": "#/rules@14"
396106
+ "$ref": "#/rules@16"
395418
396107
  },
395419
396108
  "arguments": []
395420
396109
  }
@@ -395444,7 +396133,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395444
396133
  "terminal": {
395445
396134
  "$type": "RuleCall",
395446
396135
  "rule": {
395447
- "$ref": "#/rules@14"
396136
+ "$ref": "#/rules@16"
395448
396137
  },
395449
396138
  "arguments": []
395450
396139
  }
@@ -395460,7 +396149,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395460
396149
  "terminal": {
395461
396150
  "$type": "RuleCall",
395462
396151
  "rule": {
395463
- "$ref": "#/rules@14"
396152
+ "$ref": "#/rules@16"
395464
396153
  },
395465
396154
  "arguments": []
395466
396155
  }
@@ -395490,7 +396179,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395490
396179
  "terminal": {
395491
396180
  "$type": "RuleCall",
395492
396181
  "rule": {
395493
- "$ref": "#/rules@14"
396182
+ "$ref": "#/rules@16"
395494
396183
  },
395495
396184
  "arguments": []
395496
396185
  }
@@ -395506,7 +396195,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395506
396195
  "terminal": {
395507
396196
  "$type": "RuleCall",
395508
396197
  "rule": {
395509
- "$ref": "#/rules@14"
396198
+ "$ref": "#/rules@16"
395510
396199
  },
395511
396200
  "arguments": []
395512
396201
  }
@@ -395532,7 +396221,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395532
396221
  "terminal": {
395533
396222
  "$type": "RuleCall",
395534
396223
  "rule": {
395535
- "$ref": "#/rules@14"
396224
+ "$ref": "#/rules@16"
395536
396225
  },
395537
396226
  "arguments": []
395538
396227
  }
@@ -395554,7 +396243,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395554
396243
  "terminal": {
395555
396244
  "$type": "RuleCall",
395556
396245
  "rule": {
395557
- "$ref": "#/rules@14"
396246
+ "$ref": "#/rules@16"
395558
396247
  },
395559
396248
  "arguments": []
395560
396249
  }
@@ -395576,7 +396265,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395576
396265
  "terminal": {
395577
396266
  "$type": "RuleCall",
395578
396267
  "rule": {
395579
- "$ref": "#/rules@14"
396268
+ "$ref": "#/rules@16"
395580
396269
  },
395581
396270
  "arguments": []
395582
396271
  }
@@ -395598,7 +396287,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395598
396287
  "terminal": {
395599
396288
  "$type": "RuleCall",
395600
396289
  "rule": {
395601
- "$ref": "#/rules@14"
396290
+ "$ref": "#/rules@16"
395602
396291
  },
395603
396292
  "arguments": []
395604
396293
  }
@@ -395620,7 +396309,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395620
396309
  "terminal": {
395621
396310
  "$type": "RuleCall",
395622
396311
  "rule": {
395623
- "$ref": "#/rules@14"
396312
+ "$ref": "#/rules@16"
395624
396313
  },
395625
396314
  "arguments": []
395626
396315
  }
@@ -395642,7 +396331,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395642
396331
  "terminal": {
395643
396332
  "$type": "RuleCall",
395644
396333
  "rule": {
395645
- "$ref": "#/rules@14"
396334
+ "$ref": "#/rules@16"
395646
396335
  },
395647
396336
  "arguments": []
395648
396337
  }
@@ -395664,7 +396353,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395664
396353
  "terminal": {
395665
396354
  "$type": "RuleCall",
395666
396355
  "rule": {
395667
- "$ref": "#/rules@14"
396356
+ "$ref": "#/rules@16"
395668
396357
  },
395669
396358
  "arguments": []
395670
396359
  }
@@ -395686,7 +396375,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395686
396375
  "terminal": {
395687
396376
  "$type": "RuleCall",
395688
396377
  "rule": {
395689
- "$ref": "#/rules@60"
396378
+ "$ref": "#/rules@65"
395690
396379
  },
395691
396380
  "arguments": []
395692
396381
  }
@@ -395717,7 +396406,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395717
396406
  "terminal": {
395718
396407
  "$type": "RuleCall",
395719
396408
  "rule": {
395720
- "$ref": "#/rules@61"
396409
+ "$ref": "#/rules@66"
395721
396410
  },
395722
396411
  "arguments": []
395723
396412
  }
@@ -395755,7 +396444,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395755
396444
  "terminal": {
395756
396445
  "$type": "RuleCall",
395757
396446
  "rule": {
395758
- "$ref": "#/rules@14"
396447
+ "$ref": "#/rules@16"
395759
396448
  },
395760
396449
  "arguments": []
395761
396450
  }
@@ -395774,7 +396463,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
395774
396463
  "terminal": {
395775
396464
  "$type": "RuleCall",
395776
396465
  "rule": {
395777
- "$ref": "#/rules@14"
396466
+ "$ref": "#/rules@16"
395778
396467
  },
395779
396468
  "arguments": []
395780
396469
  }
@@ -395884,8 +396573,42 @@ var WadiGeneratedModule = {
395884
396573
  parser: {}
395885
396574
  };
395886
396575
 
396576
+ // ../wadi-dsl/src/language/wadi-scope.ts
396577
+ function moduleUri(ref) {
396578
+ return URI2.parse(`memory:///${ref}.wdl`);
396579
+ }
396580
+ var WadiScopeProvider = class extends DefaultScopeProvider {
396581
+ documents;
396582
+ constructor(services) {
396583
+ super(services);
396584
+ this.documents = services.shared.workspace.LangiumDocuments;
396585
+ }
396586
+ getScope(context) {
396587
+ const isAsset = this.reflection.getReferenceType(context) === "AssetDecl";
396588
+ const model = ast_utils_exports.getDocument(context.container).parseResult.value;
396589
+ const out = [];
396590
+ const add = (node, name, d) => out.push(this.descriptions.createDescription(node, name, d));
396591
+ const collect = (m, d, prefix) => {
396592
+ if (isAsset) for (const a of m.assets) add(a, prefix ? `${prefix}.${a.id}` : a.id, d);
396593
+ else for (const c of m.components) add(c, prefix ? `${prefix}.${c.name}` : c.name, d);
396594
+ };
396595
+ const doc = ast_utils_exports.getDocument(context.container);
396596
+ collect(model, doc, "");
396597
+ for (const imp of model.imports) {
396598
+ const idoc = this.documents.getDocument(moduleUri(imp.ref));
396599
+ if (!idoc) continue;
396600
+ collect(idoc.parseResult.value, idoc, imp.ns ?? "");
396601
+ }
396602
+ return new MapScope(out);
396603
+ }
396604
+ };
396605
+
395887
396606
  // ../wadi-dsl/src/language/wadi-module.ts
395888
- var WadiModule = {};
396607
+ var WadiModule = {
396608
+ references: {
396609
+ ScopeProvider: (services) => new WadiScopeProvider(services)
396610
+ }
396611
+ };
395889
396612
  function createWadiServices(context = EmptyFileSystem) {
395890
396613
  const shared = inject(createDefaultSharedCoreModule(context), WadiGeneratedSharedModule);
395891
396614
  const Wadi = inject(createDefaultCoreModule({ shared }), WadiGeneratedModule, WadiModule);
@@ -395976,7 +396699,7 @@ function room(r2) {
395976
396699
  const items = r2.items.map(roomItem);
395977
396700
  const o = {
395978
396701
  type: "room",
395979
- name: r2.name,
396702
+ name: unquote(r2.name),
395980
396703
  x: put("x", r2.x, 0),
395981
396704
  y: put("y", r2.y, 0),
395982
396705
  width: put("width", r2.w, 1),
@@ -396004,7 +396727,7 @@ function opening(o) {
396004
396727
  const { formulas, put } = geom();
396005
396728
  const obj = {
396006
396729
  kind: o.kind,
396007
- name: o.name,
396730
+ name: unquote(o.name),
396008
396731
  offset: put("offset", o.offset, 0),
396009
396732
  width: put("width", o.width, 1),
396010
396733
  height: put("height", o.height, 1)
@@ -396012,6 +396735,7 @@ function opening(o) {
396012
396735
  const s = put("sill_height", o.sill);
396013
396736
  if (s !== void 0) obj.sill_height = s;
396014
396737
  if (o.open) obj.open = true;
396738
+ if (o.direction) obj.direction = o.direction;
396015
396739
  return done(obj, formulas);
396016
396740
  }
396017
396741
  function roomItem(it) {
@@ -396034,7 +396758,7 @@ function wall(w) {
396034
396758
  const { formulas, put } = geom();
396035
396759
  const o = {
396036
396760
  type: "wall",
396037
- name: w.name,
396761
+ name: unquote(w.name),
396038
396762
  start_x: put("start_x", w.start_x, 0),
396039
396763
  start_y: put("start_y", w.start_y, 0),
396040
396764
  end_x: put("end_x", w.end_x, 0),
@@ -396054,12 +396778,12 @@ function pillar(p) {
396054
396778
  const { formulas, put } = geom();
396055
396779
  const o = {
396056
396780
  type: "pillar",
396057
- name: p.name,
396781
+ name: unquote(p.name),
396058
396782
  x: put("x", p.x, 0),
396059
- y: put("y", p.y, 0),
396060
- width: put("width", p.w, 1),
396061
- length: put("length", p.l, 1)
396783
+ y: put("y", p.y, 0)
396062
396784
  };
396785
+ if (!p.w_auto) o.width = put("width", p.w, 1);
396786
+ if (!p.l_auto) o.length = put("length", p.l, 1);
396063
396787
  const h = put("height", p.height, 1);
396064
396788
  if (h !== void 0) o.height = h;
396065
396789
  applyCommon(o, formulas, p);
@@ -396140,12 +396864,12 @@ function staircase(s) {
396140
396864
  if (rh !== void 0) o.rise_height = rh;
396141
396865
  const mr = put("max_run", s.max_run, 1);
396142
396866
  if (mr !== void 0) o.max_run = mr;
396143
- const ld = put("landing_depth", s.landing_depth);
396867
+ const ld = put("landing_depth", s.landing_depth, 1);
396144
396868
  if (ld !== void 0) o.landing_depth = ld;
396145
396869
  const lt = put("landing_thickness", s.landing_thickness);
396146
396870
  if (lt !== void 0) o.landing_thickness = lt;
396147
396871
  if (s.turn) o.turn = s.turn;
396148
- const fg = put("flight_gap", s.flight_gap);
396872
+ const fg = put("flight_gap", s.flight_gap, 1);
396149
396873
  if (fg !== void 0) o.flight_gap = fg;
396150
396874
  applyCommon(o, formulas, s);
396151
396875
  return done(o, formulas);
@@ -396175,8 +396899,6 @@ function asset(a) {
396175
396899
  if (a.category) o.category = unquote(a.category);
396176
396900
  return o;
396177
396901
  }
396178
- var ASSET_INDEX = /* @__PURE__ */ new Map();
396179
- var NS_ASSET_INDEX = /* @__PURE__ */ new Map();
396180
396902
  function assetDeclToObj(a) {
396181
396903
  const o = {
396182
396904
  id: unquote(a.id),
@@ -396187,35 +396909,29 @@ function assetDeclToObj(a) {
396187
396909
  if (a.category) o.category = unquote(a.category);
396188
396910
  return o;
396189
396911
  }
396912
+ function unresolvedRefMessage(refText, kind, node) {
396913
+ const model = ast_utils_exports.getDocument(node).parseResult.value;
396914
+ const aliases = model.imports.filter((i2) => i2.ns).map((i2) => i2.ns);
396915
+ const verb = kind === "component" ? "use" : "item asset";
396916
+ const dot2 = refText.indexOf(".");
396917
+ if (dot2 >= 0) {
396918
+ const ns = refText.slice(0, dot2);
396919
+ const name = refText.slice(dot2 + 1);
396920
+ if (!aliases.includes(ns)) {
396921
+ return `${verb} ${refText}: no import is aliased "${ns}". Add \`import "\u2026" as ${ns}\`` + (aliases.length ? ` (imported aliases: ${aliases.join(", ")}).` : ".");
396922
+ }
396923
+ return `unknown ${kind} "${refText}" \u2014 module "${ns}" defines no "${name}".`;
396924
+ }
396925
+ const local = kind === "component" ? model.components.map((c) => c.name) : model.assets.map((a) => unquote(a.id));
396926
+ return `unknown ${kind} "${refText}". Define it here, import a module that provides it and use \`${ns_hint(kind)}\`, or check the name` + (local.length ? ` (in scope: ${local.join(", ")}).` : ".");
396927
+ }
396928
+ var ns_hint = (kind) => kind === "component" ? "use ns.Comp" : 'item ns."id"';
396190
396929
  function resolveItemAsset(it) {
396191
396930
  if (it.asset) return asset(it.asset);
396192
396931
  const ref = it.assetRef;
396193
396932
  if (!ref) throw new Error("item has no asset (expected `asset { \u2026 }` or an asset id)");
396194
- const id = unquote(ref.id);
396195
- if (ref.ns) {
396196
- const mod = NS_ASSET_INDEX.get(ref.ns);
396197
- if (!mod) {
396198
- const nss = [...NS_ASSET_INDEX.keys()];
396199
- throw new Error(
396200
- `item asset "${ref.ns}.${id}": no import is aliased "${ref.ns}". Add \`import "\u2026" as ${ref.ns}\`` + (nss.length ? ` (imported aliases: ${nss.join(", ")}).` : ".")
396201
- );
396202
- }
396203
- const decl2 = mod.get(id);
396204
- if (!decl2) {
396205
- const avail = [...mod.keys()];
396206
- throw new Error(
396207
- `unknown asset "${ref.ns}.${id}" \u2014 module "${ref.ns}" declares no "${id}"` + (avail.length ? ` (it has: ${avail.join(", ")}).` : ".")
396208
- );
396209
- }
396210
- return assetDeclToObj(decl2);
396211
- }
396212
- const decl = ASSET_INDEX.get(id);
396213
- if (!decl) {
396214
- const avail = [...ASSET_INDEX.keys()];
396215
- throw new Error(
396216
- `unknown asset "${id}". Declare it with a top-level \`asset "${id}" src \u2026 dims \u2026\`, bare-import a module that provides it, or use a namespaced \`item ns."${id}"\`` + (avail.length ? ` (in scope: ${avail.join(", ")}).` : ".")
396217
- );
396218
- }
396933
+ const decl = ref.ref;
396934
+ if (!decl) throw new Error(unresolvedRefMessage(ref.$refText, "asset", it));
396219
396935
  return assetDeclToObj(decl);
396220
396936
  }
396221
396937
  function item(it) {
@@ -396240,30 +396956,17 @@ function item(it) {
396240
396956
  applyCommon(o, formulas, it);
396241
396957
  return done(o, formulas);
396242
396958
  }
396243
- var COMPONENT_NAMES = /* @__PURE__ */ new Set();
396244
- var NS_COMPONENT_INDEX = /* @__PURE__ */ new Map();
396959
+ var joinPrefix = (prefix, ns) => prefix ? `${prefix}.${ns}` : ns;
396960
+ var flatKey = (prefix, name) => prefix ? `${prefix}.${name}` : name;
396961
+ var DOC_PREFIX = /* @__PURE__ */ new Map();
396962
+ function componentKey(def) {
396963
+ const uri = ast_utils_exports.getDocument(def).uri.toString();
396964
+ return flatKey(DOC_PREFIX.get(uri) ?? "", def.name);
396965
+ }
396245
396966
  function resolveComponentRef(c) {
396246
- if (c.ns) {
396247
- const mod = NS_COMPONENT_INDEX.get(c.ns);
396248
- if (!mod) {
396249
- const nss = [...NS_COMPONENT_INDEX.keys()];
396250
- throw new Error(
396251
- `use ${c.ns}.${c.ref}: no import is aliased "${c.ns}". Add \`import "\u2026" as ${c.ns}\`` + (nss.length ? ` (imported aliases: ${nss.join(", ")}).` : ".")
396252
- );
396253
- }
396254
- if (!mod.has(c.ref)) {
396255
- throw new Error(
396256
- `unknown component "${c.ns}.${c.ref}" \u2014 module "${c.ns}" defines no "${c.ref}"` + (mod.size ? ` (it has: ${[...mod.keys()].join(", ")}).` : ".")
396257
- );
396258
- }
396259
- return `${c.ns}.${c.ref}`;
396260
- }
396261
- if (COMPONENT_NAMES.size && !COMPONENT_NAMES.has(c.ref)) {
396262
- throw new Error(
396263
- `unknown component "${c.ref}". Define it with \`component ${c.ref} { \u2026 }\`, or import a module that provides it and use \`use ns.${c.ref}\` (in scope: ${[...COMPONENT_NAMES].join(", ")}).`
396264
- );
396265
- }
396266
- return c.ref;
396967
+ const def = c.target.ref;
396968
+ if (!def) throw new Error(unresolvedRefMessage(c.target.$refText, "component", c));
396969
+ return componentKey(def);
396267
396970
  }
396268
396971
  function componentInstance(c) {
396269
396972
  const { formulas, put } = geom();
@@ -396274,6 +396977,8 @@ function componentInstance(c) {
396274
396977
  y: put("y", c.y, 0)
396275
396978
  };
396276
396979
  if (c.name) o.name = unquote(c.name);
396980
+ const rot = put("rotation", c.rotation);
396981
+ if (rot !== void 0) o.rotation = rot;
396277
396982
  if (c.args.length) {
396278
396983
  const params = {};
396279
396984
  for (const a of c.args) params[a.name] = exprToValue(a.value);
@@ -396288,8 +396993,21 @@ function roof(r2) {
396288
396993
  if (r2.name) o.name = unquote(r2.name);
396289
396994
  if (r2.default_endpoint) o.default_endpoint = r2.default_endpoint;
396290
396995
  if (r2.slope) {
396291
- const v = exprToValue(r2.slope.value);
396292
- o.slope = r2.slope.by === "angle" ? { by: "angle", angle_deg: v } : { by: "height", ridge_h: v };
396996
+ const s = r2.slope;
396997
+ if (s.angle_left !== void 0 && s.angle_right !== void 0) {
396998
+ const l = exprToValue(s.angle_left);
396999
+ const rr = exprToValue(s.angle_right);
397000
+ if (l === rr) {
397001
+ o.slope = { by: "angle", angle_deg: l };
397002
+ } else {
397003
+ o.slope_left = { by: "angle", angle_deg: l };
397004
+ o.slope_right = { by: "angle", angle_deg: rr };
397005
+ }
397006
+ } else if (s.angle_deg !== void 0) {
397007
+ o.slope = { by: "angle", angle_deg: exprToValue(s.angle_deg) };
397008
+ } else if (s.ridge_h !== void 0) {
397009
+ o.slope = { by: "height", ridge_h: exprToValue(s.ridge_h) };
397010
+ }
396293
397011
  }
396294
397012
  const mo = put("min_overhang", r2.min_overhang);
396295
397013
  if (mo !== void 0) o.min_overhang = mo;
@@ -396301,6 +397019,7 @@ function roof(r2) {
396301
397019
  }
396302
397020
  const gwt = put("gable_wall_thickness", r2.gable_wall_thickness);
396303
397021
  if (gwt !== void 0) o.gable_wall_thickness = gwt;
397022
+ if (r2.framing) o.framing = jsonObject(r2.framing);
396304
397023
  if (r2.segments.length) o.segments = r2.segments.map(roofSegment);
396305
397024
  if (r2.trusses.length) o.trusses = r2.trusses.map(roofTruss);
396306
397025
  applyCommon(o, formulas, r2);
@@ -396407,18 +397126,59 @@ function componentDef(d) {
396407
397126
  }
396408
397127
  return def;
396409
397128
  }
396410
- var emptyScope = () => ({ bare: /* @__PURE__ */ new Map(), byNs: /* @__PURE__ */ new Map() });
396411
- var EMPTY_LINK = { assets: emptyScope(), components: emptyScope() };
396412
- function modelToHouseConfig(model, linked = EMPTY_LINK) {
397129
+ var ENTRY_URI = "memory:///__entry__.wdl";
397130
+ function linkProject(shared, text, resolveModule) {
397131
+ const docs = shared.workspace.LangiumDocuments;
397132
+ const factory = shared.workspace.LangiumDocumentFactory;
397133
+ for (const d of [...docs.all]) docs.deleteDocument(d.uri);
397134
+ const parse7 = (t, uri, what) => {
397135
+ const doc = factory.fromString(t, uri);
397136
+ const r2 = doc.parseResult;
397137
+ if (r2.lexerErrors.length || r2.parserErrors.length) {
397138
+ const msgs = [
397139
+ ...r2.lexerErrors.map((e) => `lex: ${e.message}`),
397140
+ ...r2.parserErrors.map((e) => `parse: ${e.message}`)
397141
+ ];
397142
+ throw new Error(`${what} parse failed:
397143
+ ${msgs.join("\n ")}`);
397144
+ }
397145
+ docs.addDocument(doc);
397146
+ return doc;
397147
+ };
397148
+ const hostDoc = parse7(text, URI2.parse(ENTRY_URI), "DSL");
397149
+ const modules = [];
397150
+ const prefixByUri = /* @__PURE__ */ new Map([[ENTRY_URI, ""]]);
397151
+ const parsedByRef = /* @__PURE__ */ new Map();
397152
+ const walk = (model, prefix, path) => {
397153
+ for (const imp of model.imports) {
397154
+ const ref = imp.ref;
397155
+ if (path.includes(ref)) throw new Error(`import cycle: ${[...path, ref].join(" \u2192 ")}`);
397156
+ const childPrefix = imp.ns ? joinPrefix(prefix, imp.ns) : prefix;
397157
+ const childUri = moduleUri(ref).toString();
397158
+ let doc = parsedByRef.get(ref);
397159
+ if (!doc) {
397160
+ if (!resolveModule) {
397161
+ throw new Error(
397162
+ `import "${ref}": imports need a module resolver, but none is available in this context.`
397163
+ );
397164
+ }
397165
+ const src = resolveModule(ref);
397166
+ if (src === void 0) throw new Error(`import "${ref}": module not found on the search path.`);
397167
+ doc = parse7(src, moduleUri(ref), `imported module "${ref}"`);
397168
+ parsedByRef.set(ref, doc);
397169
+ modules.push({ uri: childUri, prefix: childPrefix, model: doc.parseResult.value });
397170
+ }
397171
+ if (!prefixByUri.has(childUri)) prefixByUri.set(childUri, childPrefix);
397172
+ walk(doc.parseResult.value, childPrefix, [...path, ref]);
397173
+ }
397174
+ };
397175
+ walk(hostDoc.parseResult.value, "", []);
397176
+ for (const d of [...docs.all]) d.state = DocumentState.ComputedScopes;
397177
+ DOC_PREFIX = prefixByUri;
397178
+ return { host: hostDoc.parseResult.value, modules };
397179
+ }
397180
+ function modelToHouseConfig(model, project) {
396413
397181
  const cfg = {};
396414
- ASSET_INDEX = new Map(linked.assets.bare);
396415
- for (const a of model.assets) ASSET_INDEX.set(unquote(a.id), a);
396416
- NS_ASSET_INDEX = linked.assets.byNs;
396417
- COMPONENT_NAMES = /* @__PURE__ */ new Set([
396418
- ...model.components.map((d) => d.name),
396419
- ...linked.components.bare.keys()
396420
- ]);
396421
- NS_COMPONENT_INDEX = linked.components.byNs;
396422
397182
  if (model.convention) cfg.coord_convention = model.convention;
396423
397183
  if (model.units) {
396424
397184
  const u = { system: model.units.system };
@@ -396478,8 +397238,36 @@ function modelToHouseConfig(model, linked = EMPTY_LINK) {
396478
397238
  cfg.grids = grids;
396479
397239
  }
396480
397240
  if (model.configurators.length) {
396481
- const inputs = model.configurators[0].inputs.map(configInput);
396482
- cfg.configurator = { inputs };
397241
+ const c = model.configurators[0];
397242
+ const section = {};
397243
+ if (c.title) section.title = unquote(c.title);
397244
+ if (c.description) section.description = unquote(c.description);
397245
+ const groups = [];
397246
+ const inputs = [];
397247
+ const usedIds = /* @__PURE__ */ new Set();
397248
+ const groupId = (label) => {
397249
+ const base = label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "group";
397250
+ let id = /^[a-z_]/.test(base) ? base : `g_${base}`;
397251
+ for (let k = 2; usedIds.has(id); k++) id = `${base}_${k}`;
397252
+ usedIds.add(id);
397253
+ return id;
397254
+ };
397255
+ for (const item2 of c.items) {
397256
+ if (item2.$type === "ConfigGroup") {
397257
+ const g = item2;
397258
+ const label = unquote(g.label);
397259
+ const id = groupId(label);
397260
+ const gobj = { id, label };
397261
+ if (g.description) gobj.description = unquote(g.description);
397262
+ groups.push(gobj);
397263
+ for (const i2 of g.inputs) inputs.push({ ...configInput(i2), group: id });
397264
+ } else {
397265
+ inputs.push(configInput(item2));
397266
+ }
397267
+ }
397268
+ if (groups.length) section.groups = groups;
397269
+ section.inputs = inputs;
397270
+ cfg.configurator = section;
396483
397271
  }
396484
397272
  if (model.layers.length) {
396485
397273
  cfg.layers = model.layers.map((l) => {
@@ -396491,11 +397279,12 @@ function modelToHouseConfig(model, linked = EMPTY_LINK) {
396491
397279
  }
396492
397280
  {
396493
397281
  const comps = {};
396494
- for (const [name, d] of linked.components.bare) comps[name] = componentDef(d);
397282
+ const emit = (m) => {
397283
+ for (const d of m.model.components) comps[flatKey(m.prefix, d.name)] = componentDef(d);
397284
+ };
397285
+ for (const m of project.modules) if (m.prefix === "") emit(m);
396495
397286
  for (const d of model.components) comps[d.name] = componentDef(d);
396496
- for (const [ns, mod] of linked.components.byNs) {
396497
- for (const [name, d] of mod) comps[`${ns}.${name}`] = componentDef(d);
396498
- }
397287
+ for (const m of project.modules) if (m.prefix !== "") emit(m);
396499
397288
  if (Object.keys(comps).length) cfg.components = comps;
396500
397289
  }
396501
397290
  cfg.floors = model.floors.map((f2) => {
@@ -396507,6 +397296,7 @@ function modelToHouseConfig(model, linked = EMPTY_LINK) {
396507
397296
  if (f2.height !== void 0) floor2.height = f2.height;
396508
397297
  if (f2.wall_height !== void 0) floor2.wall_height = f2.wall_height;
396509
397298
  if (f2.slab_thickness !== void 0) floor2.slab_thickness = f2.slab_thickness;
397299
+ if (f2.enabled !== void 0) floor2.enabled = exprToValue(f2.enabled);
396510
397300
  return floor2;
396511
397301
  });
396512
397302
  return cfg;
@@ -396524,26 +397314,33 @@ function configInput(i2) {
396524
397314
  };
396525
397315
  if (s.unit) o.unit = s.unit;
396526
397316
  if (s.step !== void 0) o.step = s.step;
397317
+ if (s.description) o.description = unquote(s.description);
396527
397318
  return o;
396528
397319
  }
396529
397320
  case "NumberInput": {
396530
397321
  const n2 = i2;
396531
397322
  const o = { target: n2.target, label: unquote(n2.label), control: "number" };
396532
397323
  if (n2.unit) o.unit = n2.unit;
397324
+ if (n2.description) o.description = unquote(n2.description);
396533
397325
  return o;
396534
397326
  }
396535
397327
  case "ToggleInput": {
396536
397328
  const t = i2;
396537
- return { target: t.target, label: unquote(t.label), control: "toggle" };
397329
+ const o = { target: t.target, label: unquote(t.label), control: "toggle" };
397330
+ if (t.description) o.description = unquote(t.description);
397331
+ return o;
396538
397332
  }
396539
397333
  case "SelectInput": {
396540
397334
  const s = i2;
396541
- return {
397335
+ const o = {
396542
397336
  target: s.target,
396543
397337
  label: unquote(s.label),
396544
397338
  control: "select",
396545
- options: s.options.map((op) => ({ value: op.value, label: op.label }))
397339
+ // Option label is an ID (kept as-is) or a quoted display string (unquoted).
397340
+ options: s.options.map((op) => ({ value: op.value, label: unquote(op.label) }))
396546
397341
  };
397342
+ if (s.description) o.description = unquote(s.description);
397343
+ return o;
396547
397344
  }
396548
397345
  default:
396549
397346
  throw new Error(`unhandled configurator input: ${i2.$type}`);
@@ -396561,38 +397358,10 @@ function parseModel(services, text, what = "DSL") {
396561
397358
  }
396562
397359
  return result.value;
396563
397360
  }
396564
- function linkModules(model, services, resolveModule) {
396565
- const assets = emptyScope();
396566
- const components = emptyScope();
396567
- for (const imp of model.imports ?? []) {
396568
- const ref = unquote(imp.ref);
396569
- if (!resolveModule) {
396570
- throw new Error(
396571
- `import "${ref}": imports need a module resolver, but none is available in this context.`
396572
- );
396573
- }
396574
- const src = resolveModule(ref);
396575
- if (src === void 0) {
396576
- throw new Error(`import "${ref}": module not found on the search path.`);
396577
- }
396578
- const sub = parseModel(services, src, `imported module "${ref}"`);
396579
- const modAssets = new Map(sub.assets.map((a) => [unquote(a.id), a]));
396580
- const modComponents = new Map(sub.components.map((d) => [d.name, d]));
396581
- if (imp.ns) {
396582
- assets.byNs.set(imp.ns, modAssets);
396583
- components.byNs.set(imp.ns, modComponents);
396584
- } else {
396585
- for (const [id, a] of modAssets) assets.bare.set(id, a);
396586
- for (const [name, d] of modComponents) components.bare.set(name, d);
396587
- }
396588
- }
396589
- return { assets, components };
396590
- }
396591
397361
  function compileDsl(text, opts = {}) {
396592
- const services = createWadiServices(EmptyFileSystem).Wadi;
396593
- const model = parseModel(services, text);
396594
- const linked = linkModules(model, services, opts.resolveModule);
396595
- return modelToHouseConfig(model, linked);
397362
+ const { shared } = createWadiServices(EmptyFileSystem);
397363
+ const project = linkProject(shared, text, opts.resolveModule);
397364
+ return modelToHouseConfig(project.host, project);
396596
397365
  }
396597
397366
  function moduleExports3(text) {
396598
397367
  const services = createWadiServices(EmptyFileSystem).Wadi;
@@ -411498,6 +412267,10 @@ var componentObject = external_exports2.object({
411498
412267
  params: external_exports2.record(external_exports2.string(), external_exports2.union([external_exports2.number(), external_exports2.string()])).optional(),
411499
412268
  x: external_exports2.number(),
411500
412269
  y: external_exports2.number(),
412270
+ // Standard placement: yaw° about the instance origin (clockwise, same sense as
412271
+ // item rotation: 0=south, 90=east). Right angles (0/90/180/270) are exact for
412272
+ // any component; a non-right angle is allowed only for furniture-only ones.
412273
+ rotation: external_exports2.number().optional(),
411501
412274
  z_offset: external_exports2.number().optional()
411502
412275
  }).strict();
411503
412276
  var itemObject = external_exports2.object({
@@ -412188,23 +412961,66 @@ function stripOpenings(obj) {
412188
412961
  return obj;
412189
412962
  }
412190
412963
  var MAX_COMPONENT_DEPTH = 8;
412191
- function offsetObjects(objs, dx, dy, dz) {
412964
+ var BOX_TYPES = /* @__PURE__ */ new Set(["room", "pillar", "beam", "floor_slab", "plinth", "ground"]);
412965
+ var ANY_ANGLE_TYPES = /* @__PURE__ */ new Set(["item", "wall"]);
412966
+ var SIDE_NORMAL = {
412967
+ north: [0, -1],
412968
+ south: [0, 1],
412969
+ east: [1, 0],
412970
+ west: [-1, 0]
412971
+ };
412972
+ function rotateSide(side2, cos, sin) {
412973
+ const [nx, ny] = SIDE_NORMAL[side2];
412974
+ const rx = nx * cos + ny * sin;
412975
+ const ry = -nx * sin + ny * cos;
412976
+ if (Math.abs(rx) >= Math.abs(ry)) return rx >= 0 ? "east" : "west";
412977
+ return ry >= 0 ? "south" : "north";
412978
+ }
412979
+ var isSide = (s) => typeof s === "string" && SIDES.includes(s);
412980
+ function placeComponent(objs, dx, dy, dz, deg, wallThickness) {
412981
+ const norm = (deg % 360 + 360) % 360;
412982
+ const rad = norm * Math.PI / 180;
412983
+ const clean = (v) => Math.round(v * 1e12) / 1e12;
412984
+ const cos = clean(Math.cos(rad));
412985
+ const sin = clean(Math.sin(rad));
412986
+ const swap = norm === 90 || norm === 270;
412987
+ const rp = (x, y) => [x * cos + y * sin, -x * sin + y * cos];
412192
412988
  return objs.map((o) => {
412193
412989
  const n2 = { ...o };
412194
- if (typeof n2.x === "number") n2.x = n2.x + dx;
412195
- if (typeof n2.y === "number") n2.y = n2.y + dy;
412196
- if (typeof n2.start_x === "number") n2.start_x = n2.start_x + dx;
412197
- if (typeof n2.end_x === "number") n2.end_x = n2.end_x + dx;
412198
- if (typeof n2.start_y === "number") n2.start_y = n2.start_y + dy;
412199
- if (typeof n2.end_y === "number") n2.end_y = n2.end_y + dy;
412200
- if (Array.isArray(n2.path)) {
412201
- n2.path = n2.path.map(
412202
- (pt) => Array.isArray(pt) && pt.length >= 2 ? [pt[0] + dx, pt[1] + dy] : pt
412203
- );
412204
- }
412205
- if (dz !== 0) {
412206
- n2.z_offset = (typeof n2.z_offset === "number" ? n2.z_offset : 0) + dz;
412207
- }
412990
+ if (norm !== 0) {
412991
+ if (BOX_TYPES.has(n2.type)) {
412992
+ const w = typeof n2.width === "number" ? n2.width : wallThickness;
412993
+ const l = typeof n2.length === "number" ? n2.length : wallThickness;
412994
+ const [rcx, rcy] = rp(n2.x + w / 2, n2.y + l / 2);
412995
+ const w2 = swap ? l : w, l2 = swap ? w : l;
412996
+ n2.x = rcx - w2 / 2;
412997
+ n2.y = rcy - l2 / 2;
412998
+ n2.width = w2;
412999
+ n2.length = l2;
413000
+ } else if (typeof n2.x === "number" && typeof n2.y === "number") {
413001
+ [n2.x, n2.y] = rp(n2.x, n2.y);
413002
+ }
413003
+ if (typeof n2.start_x === "number" && typeof n2.start_y === "number") [n2.start_x, n2.start_y] = rp(n2.start_x, n2.start_y);
413004
+ if (typeof n2.end_x === "number" && typeof n2.end_y === "number") [n2.end_x, n2.end_y] = rp(n2.end_x, n2.end_y);
413005
+ if (Array.isArray(n2.path)) n2.path = n2.path.map((pt) => Array.isArray(pt) && pt.length >= 2 ? rp(pt[0], pt[1]) : pt);
413006
+ if (isSide(n2.direction)) n2.direction = rotateSide(n2.direction, cos, sin);
413007
+ if (isSide(n2.facing)) n2.facing = rotateSide(n2.facing, cos, sin);
413008
+ if (Array.isArray(n2.walls)) n2.walls = n2.walls.map((s) => isSide(s) ? rotateSide(s, cos, sin) : s);
413009
+ if (n2.wall_heights && typeof n2.wall_heights === "object") {
413010
+ const wh = {};
413011
+ for (const [k, v] of Object.entries(n2.wall_heights)) wh[isSide(k) ? rotateSide(k, cos, sin) : k] = v;
413012
+ n2.wall_heights = wh;
413013
+ }
413014
+ if (n2.type === "item") n2.rotation = (((typeof n2.rotation === "number" ? n2.rotation : 0) + norm) % 360 + 360) % 360;
413015
+ }
413016
+ if (typeof n2.x === "number") n2.x += dx;
413017
+ if (typeof n2.y === "number") n2.y += dy;
413018
+ if (typeof n2.start_x === "number") n2.start_x += dx;
413019
+ if (typeof n2.end_x === "number") n2.end_x += dx;
413020
+ if (typeof n2.start_y === "number") n2.start_y += dy;
413021
+ if (typeof n2.end_y === "number") n2.end_y += dy;
413022
+ if (Array.isArray(n2.path)) n2.path = n2.path.map((pt) => Array.isArray(pt) && pt.length >= 2 ? [pt[0] + dx, pt[1] + dy] : pt);
413023
+ if (dz !== 0) n2.z_offset = (typeof n2.z_offset === "number" ? n2.z_offset : 0) + dz;
412208
413024
  if ("formulas" in n2) delete n2.formulas;
412209
413025
  return n2;
412210
413026
  });
@@ -412247,7 +413063,16 @@ function expandComponent(inst, hostConfig, wallThickness, opts, depth) {
412247
413063
  const dx = typeof inst.x === "number" ? inst.x : 0;
412248
413064
  const dy = typeof inst.y === "number" ? inst.y : 0;
412249
413065
  const dz = typeof inst.z_offset === "number" ? inst.z_offset : 0;
412250
- return offsetObjects(bodyObjs, dx, dy, dz);
413066
+ const deg = typeof inst.rotation === "number" ? inst.rotation : 0;
413067
+ if ((deg % 90 + 90) % 90 !== 0) {
413068
+ const bad = bodyObjs.find((b) => !ANY_ANGLE_TYPES.has(String(b.type)));
413069
+ if (bad) {
413070
+ throw new Error(
413071
+ `component '${ref}' rotation ${deg}\xB0 is not a right angle \u2014 its ${String(bad.type)}${bad.name ? ` '${String(bad.name)}'` : ""} can't rotate to a non-right angle. Use 0/90/180/270 for structural components; free angles are for furniture-only components.`
413072
+ );
413073
+ }
413074
+ }
413075
+ return placeComponent(bodyObjs, dx, dy, dz, deg, wallThickness);
412251
413076
  }
412252
413077
  function expandObject(obj, wallThickness) {
412253
413078
  if (obj.type === "room") return expandRoom(obj, wallThickness);
@@ -412601,6 +413426,27 @@ function resolveRise(slope, crossHalf) {
412601
413426
  if (slope.by === "height") return slope.ridge_h;
412602
413427
  return crossHalf * Math.tan(slope.angle_deg * Math.PI / 180);
412603
413428
  }
413429
+ function slopeAngleRad(spec, crossHalf) {
413430
+ if (spec.by === "angle") return spec.angle_deg * Math.PI / 180;
413431
+ return Math.atan(spec.ridge_h / crossHalf);
413432
+ }
413433
+ function resolvePitch(seg, cfg, crossHalf) {
413434
+ const left = seg.slope_left_override ?? cfg.slope_left;
413435
+ const right = seg.slope_right_override ?? cfg.slope_right;
413436
+ if (left && right) {
413437
+ const tanL = Math.tan(slopeAngleRad(left, crossHalf));
413438
+ const tanR = Math.tan(slopeAngleRad(right, crossHalf));
413439
+ if (tanL > 0 && tanR > 0) {
413440
+ const width = 2 * crossHalf;
413441
+ const ridgeH2 = width * tanL * tanR / (tanL + tanR);
413442
+ const leftRun = ridgeH2 / tanL;
413443
+ return { ridgeH: ridgeH2, ridgeShift: crossHalf - leftRun, leftPitchTan: tanL, rightPitchTan: tanR };
413444
+ }
413445
+ }
413446
+ const ridgeH = resolveRise(seg.slope_override ?? cfg.slope, crossHalf);
413447
+ const t = ridgeH / crossHalf;
413448
+ return { ridgeH, ridgeShift: 0, leftPitchTan: t, rightPitchTan: t };
413449
+ }
412604
413450
  function to3D(pt, z2) {
412605
413451
  return [pt[0], pt[1], z2];
412606
413452
  }
@@ -412643,8 +413489,8 @@ function derivePitchedRoof(cfg, opts) {
412643
413489
  const alongLen = segmentLength(seg);
412644
413490
  if (alongLen === 0) continue;
412645
413491
  const crossHalf = seg.width / 2;
412646
- const slope = seg.slope_override ?? cfg.slope;
412647
- const ridgeH = resolveRise(slope, crossHalf);
413492
+ const { ridgeH, ridgeShift, leftPitchTan, rightPitchTan } = resolvePitch(seg, cfg, crossHalf);
413493
+ const asym = ridgeShift !== 0;
412648
413494
  if (!(ridgeH > 0)) {
412649
413495
  throw new Error(`pitched segment ${seg.id}: rise must be > 0`);
412650
413496
  }
@@ -412664,10 +413510,10 @@ function derivePitchedRoof(cfg, opts) {
412664
413510
  const ridgeZ = opts.wallTopZ + ridgeH;
412665
413511
  const ohLeft = seg.overhang_left ?? minOverhang;
412666
413512
  const ohRight = seg.overhang_right ?? minOverhang;
412667
- const eaveZLeft = opts.wallTopZ - ohLeft * ridgeH / dCrit;
412668
- const eaveZRight = opts.wallTopZ - ohRight * ridgeH / dCrit;
412669
- const oCrossLeft = ohLeft * crossHalf / dCrit;
412670
- const oCrossRight = ohRight * crossHalf / dCrit;
413513
+ const eaveZLeft = asym ? opts.wallTopZ - ohLeft * leftPitchTan : opts.wallTopZ - ohLeft * ridgeH / dCrit;
413514
+ const eaveZRight = asym ? opts.wallTopZ - ohRight * rightPitchTan : opts.wallTopZ - ohRight * ridgeH / dCrit;
413515
+ const oCrossLeft = asym ? ohLeft : ohLeft * crossHalf / dCrit;
413516
+ const oCrossRight = asym ? ohRight : ohRight * crossHalf / dCrit;
412671
413517
  const oStart = startRes === "closed" ? minOverhang * hipSetbackStart / dCrit : startRes === "open" ? gableOverhangStart : 0;
412672
413518
  const oEnd = endRes === "closed" ? minOverhang * hipSetbackEnd / dCrit : endRes === "open" ? gableOverhangEnd : 0;
412673
413519
  const unit = segmentUnitVector(seg);
@@ -412679,8 +413525,16 @@ function derivePitchedRoof(cfg, opts) {
412679
413525
  const backRight = shift(startBase, rightN, crossHalf + oCrossRight);
412680
413526
  const frontLeft = shift(endBase, leftN, crossHalf + oCrossLeft);
412681
413527
  const frontRight = shift(endBase, rightN, crossHalf + oCrossRight);
412682
- const ridgeStart2D = startRes === "closed" ? shift(seg.start, unit, +hipSetbackStart) : startRes === "open" ? shift(seg.start, unit, -gableOverhangStart) : seg.start;
412683
- const ridgeEnd2D = endRes === "closed" ? shift(seg.end, unit, -hipSetbackEnd) : endRes === "open" ? shift(seg.end, unit, +gableOverhangEnd) : seg.end;
413528
+ const ridgeStart2D = shift(
413529
+ startRes === "closed" ? shift(seg.start, unit, +hipSetbackStart) : startRes === "open" ? shift(seg.start, unit, -gableOverhangStart) : seg.start,
413530
+ leftN,
413531
+ ridgeShift
413532
+ );
413533
+ const ridgeEnd2D = shift(
413534
+ endRes === "closed" ? shift(seg.end, unit, -hipSetbackEnd) : endRes === "open" ? shift(seg.end, unit, +gableOverhangEnd) : seg.end,
413535
+ leftN,
413536
+ ridgeShift
413537
+ );
412684
413538
  const ridgeStart3D = to3D(ridgeStart2D, ridgeZ);
412685
413539
  const ridgeEnd3D = to3D(ridgeEnd2D, ridgeZ);
412686
413540
  planes.push({
@@ -412815,7 +413669,8 @@ function derivePitchedRoof(cfg, opts) {
412815
413669
  if (startRes === "open") {
412816
413670
  const wallLeft = shift(seg.start, leftN, crossHalf);
412817
413671
  const wallRight = shift(seg.start, rightN, crossHalf);
412818
- const apexAtWall = [seg.start[0], seg.start[1], ridgeZ];
413672
+ const apexCross = shift(seg.start, leftN, ridgeShift);
413673
+ const apexAtWall = [apexCross[0], apexCross[1], ridgeZ];
412819
413674
  planes.push({
412820
413675
  id: `${seg.id}.gable_wall.start`,
412821
413676
  vertices: [
@@ -412876,7 +413731,8 @@ function derivePitchedRoof(cfg, opts) {
412876
413731
  if (endRes === "open") {
412877
413732
  const wallLeft = shift(seg.end, leftN, crossHalf);
412878
413733
  const wallRight = shift(seg.end, rightN, crossHalf);
412879
- const apexAtWall = [seg.end[0], seg.end[1], ridgeZ];
413734
+ const apexCross = shift(seg.end, leftN, ridgeShift);
413735
+ const apexAtWall = [apexCross[0], apexCross[1], ridgeZ];
412880
413736
  planes.push({
412881
413737
  id: `${seg.id}.gable_wall.end`,
412882
413738
  vertices: [
@@ -412937,9 +413793,10 @@ function derivePitchedRoof(cfg, opts) {
412937
413793
  if (segTrussEntry) {
412938
413794
  for (let ti = 0; ti < segTrussEntry.positions_along.length; ti++) {
412939
413795
  const along = segTrussEntry.positions_along[ti];
412940
- const apex2D = interpolatePoint(seg, along);
412941
- const leftBase = shift(apex2D, leftN, crossHalf);
412942
- const rightBase = shift(apex2D, rightN, crossHalf);
413796
+ const centre2D = interpolatePoint(seg, along);
413797
+ const leftBase = shift(centre2D, leftN, crossHalf);
413798
+ const rightBase = shift(centre2D, rightN, crossHalf);
413799
+ const apex2D = shift(centre2D, leftN, ridgeShift);
412943
413800
  trusses.push({
412944
413801
  id: `${seg.id}.truss.${ti}`,
412945
413802
  bottom_left: to3D(leftBase, opts.wallTopZ),
@@ -413522,11 +414379,18 @@ function shedZAt(cfg, seg, pt, opts) {
413522
414379
  return opts.wallTopZ + frac * rise;
413523
414380
  }
413524
414381
  function ridgeZFromConfig(cfg, wallTopZ) {
413525
- if (!cfg.slope) throw new Error("ridgeZFromConfig: cfg.slope required");
413526
- if (cfg.slope.by === "height") return wallTopZ + cfg.slope.ridge_h;
413527
414382
  const widths = cfg.segments.map((s) => s.width);
413528
- const meanHalf = widths.reduce((a, b) => a + b, 0) / widths.length / 2;
413529
- return wallTopZ + meanHalf * Math.tan(cfg.slope.angle_deg * Math.PI / 180);
414383
+ const meanHalf = widths.length ? widths.reduce((a, b) => a + b, 0) / widths.length / 2 : 0;
414384
+ const tanOf = (s) => s.by === "height" ? (s.ridge_h ?? 0) / (meanHalf || 1) : Math.tan((s.angle_deg ?? 0) * Math.PI / 180);
414385
+ if (cfg.slope) {
414386
+ if (cfg.slope.by === "height") return wallTopZ + cfg.slope.ridge_h;
414387
+ return wallTopZ + meanHalf * Math.tan(cfg.slope.angle_deg * Math.PI / 180);
414388
+ }
414389
+ if (cfg.slope_left && cfg.slope_right && meanHalf > 0) {
414390
+ const tL = tanOf(cfg.slope_left), tR = tanOf(cfg.slope_right);
414391
+ if (tL > 0 && tR > 0) return wallTopZ + 2 * meanHalf * tL * tR / (tL + tR);
414392
+ }
414393
+ throw new Error("ridgeZFromConfig: cfg.slope (or slope_left + slope_right) required");
413530
414394
  }
413531
414395
 
413532
414396
  // ../editor/src/svg2d/roof/v2/truss.ts
@@ -414370,6 +415234,72 @@ function sideHasWall(segs, seg) {
414370
415234
  }
414371
415235
  return false;
414372
415236
  }
415237
+ function openLabel(op) {
415238
+ const kind = typeof op.kind === "string" ? op.kind : "opening";
415239
+ const nm = typeof op.name === "string" && op.name ? ` "${op.name}"` : "";
415240
+ return `${kind}${nm}`;
415241
+ }
415242
+ function collectOpeningSegs(objs) {
415243
+ const out = [];
415244
+ for (const o of objs) {
415245
+ if (o.type === "room") {
415246
+ const walls = o.walls;
415247
+ if (!walls || typeof walls !== "object" || Array.isArray(walls)) continue;
415248
+ const rx = num2(o.x), ry = num2(o.y), rw = num2(o.width), rl = num2(o.length);
415249
+ for (const side2 of ALL_SIDES) {
415250
+ const ops = walls[side2]?.openings;
415251
+ if (!Array.isArray(ops)) continue;
415252
+ for (const op of ops) {
415253
+ const off = num2(op.offset), w = num2(op.width);
415254
+ const owner = `room ${objLabel(o)} ${side2}`;
415255
+ const label = openLabel(op);
415256
+ if (side2 === "north") out.push({ horiz: true, at: ry, lo: rx + off, hi: rx + off + w, owner, label });
415257
+ else if (side2 === "south") out.push({ horiz: true, at: ry + rl, lo: rx + off, hi: rx + off + w, owner, label });
415258
+ else if (side2 === "west") out.push({ horiz: false, at: rx, lo: ry + off, hi: ry + off + w, owner, label });
415259
+ else out.push({ horiz: false, at: rx + rw, lo: ry + off, hi: ry + off + w, owner, label });
415260
+ }
415261
+ }
415262
+ } else if (o.type === "wall") {
415263
+ const ops = o.openings;
415264
+ if (!Array.isArray(ops)) continue;
415265
+ const sx = num2(o.start_x), sy = num2(o.start_y), ex = num2(o.end_x), ey = num2(o.end_y);
415266
+ const horiz = Math.abs(sy - ey) < 1, vert = Math.abs(sx - ex) < 1;
415267
+ if (!horiz && !vert) continue;
415268
+ const start = horiz ? Math.min(sx, ex) : Math.min(sy, ey);
415269
+ for (const op of ops) {
415270
+ const off = num2(op.offset), w = num2(op.width);
415271
+ out.push({ horiz, at: horiz ? sy : sx, lo: start + off, hi: start + off + w, owner: `wall ${objLabel(o)}`, label: openLabel(op) });
415272
+ }
415273
+ }
415274
+ }
415275
+ return out;
415276
+ }
415277
+ var FEET_PER_METER2 = 3.280839895;
415278
+ var FEET_PER_DISPLAY = {
415279
+ feet_inches: 1,
415280
+ feet: 1,
415281
+ meters: 3.280839895,
415282
+ centimeters: 0.032808399,
415283
+ millimeters: 3280839e-9
415284
+ };
415285
+ function itemMetersToUnits(m, units) {
415286
+ const perUnit = units?.per_unit ?? 10;
415287
+ const fpu = FEET_PER_DISPLAY[units?.system ?? "feet_inches"] ?? 1;
415288
+ return m * (perUnit / fpu) * FEET_PER_METER2;
415289
+ }
415290
+ function itemBox(it, units) {
415291
+ const asset2 = it.asset;
415292
+ if (!asset2?.dimensions) return null;
415293
+ const scale = it.scale != null ? num2(it.scale) : 1;
415294
+ const fw = itemMetersToUnits(asset2.dimensions[0], units) * scale;
415295
+ const fd = itemMetersToUnits(asset2.dimensions[2], units) * scale;
415296
+ const th = num2(it.rotation) * Math.PI / 180;
415297
+ const c = Math.abs(Math.cos(th)), s = Math.abs(Math.sin(th));
415298
+ const hx = fw / 2 * c + fd / 2 * s;
415299
+ const hy = fw / 2 * s + fd / 2 * c;
415300
+ const cx = num2(it.x), cy = num2(it.y);
415301
+ return { x0: cx - hx, y0: cy - hy, x1: cx + hx, y1: cy + hy };
415302
+ }
414373
415303
  function lintStructure(config3) {
414374
415304
  const cfg = config3;
414375
415305
  const floors = cfg.floors ?? [];
@@ -414381,6 +415311,13 @@ function lintStructure(config3) {
414381
415311
  const findings = [];
414382
415312
  const rects = buildRoomRects(config3);
414383
415313
  const wallSegs = collectWallSegments(floors);
415314
+ const units = cfg.units;
415315
+ let expandedFloors = [];
415316
+ try {
415317
+ expandedFloors = expandRoomWalls(config3, void 0, { lenient: true }).floors ?? [];
415318
+ } catch {
415319
+ expandedFloors = [];
415320
+ }
414384
415321
  let baseZ = 0;
414385
415322
  for (let fi = 0; fi < floors.length; fi++) {
414386
415323
  const fl = floors[fi];
@@ -414484,6 +415421,49 @@ function lintStructure(config3) {
414484
415421
  }
414485
415422
  }
414486
415423
  }
415424
+ {
415425
+ const segs = collectOpeningSegs(objs);
415426
+ const OVERLAP = 1;
415427
+ for (let a = 0; a < segs.length; a++) {
415428
+ for (let b = a + 1; b < segs.length; b++) {
415429
+ const A = segs[a], B = segs[b];
415430
+ if (A.horiz !== B.horiz) continue;
415431
+ if (Math.abs(A.at - B.at) > 1.5) continue;
415432
+ const overlap = Math.min(A.hi, B.hi) - Math.max(A.lo, B.lo);
415433
+ if (overlap <= OVERLAP) continue;
415434
+ const by = Math.round(overlap);
415435
+ findings.push({
415436
+ rule: "C6",
415437
+ level: "error",
415438
+ floor: fnum,
415439
+ where: A.owner,
415440
+ message: A.owner === B.owner ? `${cap(floorLabel(fl))}: ${A.label} and ${B.label} overlap by ~${by} units on ${A.owner}. Two openings can't occupy the same span of a wall \u2014 move or narrow one.` : `${cap(floorLabel(fl))}: ${A.label} on ${A.owner} overlaps ${B.label} on ${B.owner} by ~${by} units \u2014 they sit on the same shared wall and collide. Offset or resize one.`
415441
+ });
415442
+ }
415443
+ }
415444
+ }
415445
+ {
415446
+ const expObjs = (expandedFloors[fi]?.objects ?? []).filter(
415447
+ (o) => o.type === "item" && o.enabled !== false
415448
+ );
415449
+ const boxes = expObjs.map((o) => ({ o, box: itemBox(o, units) })).filter((e) => e.box);
415450
+ const MARGIN = 2;
415451
+ for (let a = 0; a < boxes.length; a++) {
415452
+ for (let b = a + 1; b < boxes.length; b++) {
415453
+ const A = boxes[a], B = boxes[b];
415454
+ const ox = Math.min(A.box.x1, B.box.x1) - Math.max(A.box.x0, B.box.x0);
415455
+ const oy = Math.min(A.box.y1, B.box.y1) - Math.max(A.box.y0, B.box.y0);
415456
+ if (ox <= MARGIN || oy <= MARGIN) continue;
415457
+ findings.push({
415458
+ rule: "C7",
415459
+ level: "warn",
415460
+ floor: fnum,
415461
+ where: objLabel(A.o),
415462
+ message: `${cap(floorLabel(fl))}: furniture ${objLabel(A.o)} and ${objLabel(B.o)} overlap (~${Math.round(ox)}\xD7${Math.round(oy)} units). Reposition one if that isn't intentional.`
415463
+ });
415464
+ }
415465
+ }
415466
+ }
414487
415467
  }
414488
415468
  return findings;
414489
415469
  }
@@ -414665,8 +415645,10 @@ function svgDrawItem(cx, cy, w, l, yawDeg = 0) {
414665
415645
  const fx = Math.sin(r2), fy = Math.cos(r2);
414666
415646
  const px = -fy, py = fx;
414667
415647
  const ex = cx + fx * (l / 2), ey = cy + fy * (l / 2);
414668
- const hw = Math.min(w * 0.35, Math.min(w, l) * 0.28);
414669
- const hh = Math.min(w, l) * 0.22;
415648
+ const NOTCH_HALF_W = 3.5;
415649
+ const NOTCH_H = 5;
415650
+ const hw = Math.min(NOTCH_HALF_W, w * 0.45);
415651
+ const hh = Math.min(NOTCH_H, Math.min(w, l) * 0.45);
414670
415652
  const p1 = `${fFloat(ex + px * hw)},${fFloat(ey + py * hw)}`;
414671
415653
  const p2 = `${fFloat(ex - px * hw)},${fFloat(ey - py * hw)}`;
414672
415654
  const tip = `${fFloat(ex + fx * hh)},${fFloat(ey + fy * hh)}`;
@@ -418017,11 +418999,11 @@ var DOCS = {
418017
418999
  },
418018
419000
  "dsl": {
418019
419001
  "title": "The Wadi DSL (.wdl) \u2014 syntax reference",
418020
- "body": '# The Wadi DSL (`.wdl`) \u2014 authoring reference\n\nYou author houses in the **Wadi DSL** \u2014 a small, formal language (`.wdl`) that\ncompiles to a resolved `.wadi` (`house_config.json`). The DSL is **complete**:\nevery object type in the model has first-class syntax, so you rarely need the\n`raw` escape. Authoring the DSL is more direct and less error-prone than writing\nJSON \u2014 the grammar enforces structure, and `check.sh` reports parse errors with\nline:col.\n\n**This file is the SYNTAX reference.** The *semantics* live in the other\nreferences and apply unchanged \u2014 read them:\n\n- `coordinate-system.md` \u2014 X\u2192right, **Y\u2192DOWN**, Z\u2192up; **10 units = 1 ft**;\n the **centreline** convention. The #1 source of mistakes.\n- `conventions.md` \u2014 the **structural coding conventions** (`check.sh` enforces\n them): plinth-floor height must match the plinth block, rooms must wall every\n exterior side, a no-slab floor must set `slab_thickness 0`.\n- `parametric-conventions.md` \u2014 the grid-first recipe for reusable templates.\n- `roof-v2-guide.md` \u2014 roof segments, hip vs gable, trusses, joints.\n- `data-model.md` \u2014 the underlying `.wadi` schema (what the DSL compiles to; also\n the field reference for the `raw` escape).\n\n## The loop\n\n1. Write / edit `house.wdl` \u2014 the **single shared source** (you and the human\n co-edit it; the app\'s DSL previewer renders it live). You never produce a `.wadi`.\n2. `wadi-skill/architect/scripts/check.sh house.wdl` \u2014 runs the DSL compiler +\n validator (schema + wall/roof geometry) against a **throwaway temp** just for\n feedback; fix any reported error and re-run.\n3. `preview.sh house.wdl` \u2192 read the PNGs (plans / elevations / roof) to check your\n work. (It also compiles to a throwaway temp \u2014 no persistent `.wadi`.)\n\n## Skeleton\n\n```wdl\nhouse MyHouse {\n convention center // ALWAYS use center (wall-centreline coords)\n units feet_inches per_unit 10 // 10 project units = 1 ft\n site { plot (WIDTH, LENGTH) ref (0, 0) }\n defaults { floor_height 120 wall_height 108 slab_thickness 8 wall_thickness 8 }\n\n // parametric core (optional): var, point, grid, configurator\n // component / layer declarations (optional)\n floor 0 "Plinth" { \u2026 } // floors stack in source order (0 = plinth)\n floor 1 "Ground Floor" { \u2026 }\n floor 2 "Loft" { roof \u2026 } // roof lives ALONE on its own top floor\n}\n```\n\nNumbers are **project units** (feet \xD7 10 by default). Names after `house`,\n`room`, `pillar`, `var`, `point`, `grid`, and `use`/`component` are bare\nidentifiers (no spaces); names introduced with the `name` keyword are quoted\nstrings.\n\n## Parametric core (domain-neutral)\n\n```wdl\nvar wallT = 8 // a knob; may reference other vars\nvar pilInset = (pillarW - wallT) / 2\n\npoint House { x = 420, y = 470 } // reference as House.x / House.W / House.L\n // (.W = x, .L = y \u2014 a point doubles as a size)\n\ngrid main { // named wall centrelines; publishes main.x1 / main.yA\n x: 1 @ wallT / 2, 2 @ House.W / 2, 3 @ House.W - wallT / 2\n y: A @ wallT / 2, B @ House.L / 2, C @ House.L - wallT / 2\n}\n// each line may add: \u2026 @ <expr> thick <expr> role structural|planning\n\nconfigurator { // the knobs a downstream user turns\n slider pillarW "Column size" ft [8 .. 14 step 1]\n number ceiling "Ceiling height" ft\n toggle has_loft "Add a loft"\n select roof_style "Roof style" { Flat = 0, Shed = 1, Gable = 2, Hip = 3 }\n}\n```\n\n**Formulas are automatic.** Any geometry number can be a formula \u2014 just write the\nexpression instead of a literal (`at (main.x1, main.yA)`, `size (House.W/2, 200)`).\nOperators: `+ - * /`, unary `-`, parentheses, and the functions\n`min max clamp round floor ceil abs`. References: a `var`, a `point`\n(`House.W`), or a grid line (`main.x3 - main.x1`). No comparison operators \u2014 gate\nthings with the `min/abs` idiom (see `enabled` below).\n\n## Common attribute tail (every object)\n\nAfter an object\'s geometry, in THIS order, any of:\n\n```\n\u2026 z_offset <expr> enabled <expr> layer "id" [material "id"]\n```\n\n- `enabled <expr>` \u2014 the on/off switch. A `0`/`false` value hides the object. To\n gate on a configurator variable, use a 0/1 formula:\n `enabled 1 - min(1, abs(roof_style - 3))` renders the object only when\n `roof_style == 3`. (This is how one template carries several roofs and shows\n only the chosen one.)\n- `z_offset <expr>` \u2014 lift above the floor base (split levels).\n- `material "id"` \u2014 only on plinth / ground / room / wall / staircase / kitchen /\n roof.\n\n## Objects \u2014 structure & envelope\n\n```wdl\nslab [name "N"] at (x,y) size (w,l) [thickness <t>] // floor_slab\nbeam [name "N"] at (x,y) size (w,l) [height <h>]\nplinth [name "N"] at (x,y) size (w,l) height <h> // raised base (Plinth floor)\nground [name "N"] at (x,y) size (w,l) [height <h>] // terrain plane\npillar Name at (x,y) size (w,l) [height <h>] // (x,y) = TOP-LEFT corner\n```\n\n`at (x,y)` is the **TOP-LEFT CORNER** \u2014 **not the centre** \u2014 for every one of these\n(same as rooms/slabs/beams); `size (w,l)` is width \xD7 length. All accept the common tail.\n\n**Pillars catch people out here.** A column reads as "placed at a point," but `at` is\nstill its corner. To **centre a column on a point** `(cx, cy)` \u2014 a grid node, a room\ncorner \u2014 place it at **`at (cx - w/2, cy - l/2)`**, never at `(cx, cy)`. On a grid, the\n`pilInset` idiom (see `parametric-conventions.md`) does exactly this so columns sit flush.\n\n## Objects \u2014 rooms, walls & openings\n\nA room shows exactly the walls you declare. A **bare room (no `wall` lines) is\nenclosed on all four sides.** List plain walls compactly; give a wall its own line\nonly when it carries a door/window; omit a side to leave it open (verandah).\n\n```wdl\nroom Name at (x,y) size (w,l) [height <h>] [material "\u2026"] {\n wall east west north // plain walls \u2014 several in one statement\n wall south { door Main at <offset> size (w,h) [open] } // wall WITH openings: one side\n wall west { window W at <offset> size (w,h) [sill <s>] [open] }\n item asset { \u2026 } anchor center [gap (gx,gy)] // furniture anchored inside the room\n}\n```\n\n- `wall <side>\u2026` sides are `north|south|east|west`. A `wall <side>` line may also\n add `height <h>` / `height_end <h>` (sloped).\n- `door`/`window` `at <offset>` is measured along the wall from its start;\n `size (width, height)`; `window \u2026 sill <s>` sets the sill height; `open` = a bare\n hole (no leaf/glazing).\n\nA **free-standing wall** (not a room side):\n\n```wdl\nwall Name from (x1,y1) to (x2,y2) [height <h>] [height_end <h>] [facing north|\u2026] {\n \u2026 door/window openings \u2026\n}\n```\n\n- `from`/`to` are the wall\'s **centreline** endpoints; the wall is drawn as a rectangle\n `wall_thickness` wide, centred on that line.\n- **Overlap walls at corners \u2014 they do NOT auto-mitre.** Two free-standing walls that\n merely *touch* at a shared endpoint leave an unfilled square notch (\xBD\xB7`wall_thickness`)\n at the corner, because each is just a rectangle capped at its endpoint. To fill the\n corner, **extend the endpoints so the wall bodies OVERLAP** \u2014 run at least one wall\'s\n end **half the wall thickness past** the shared point (overlapping by the full thickness\n is fine and simplest). For an L of thickness 8 meeting at `(160,40)`:\n\n ```wdl\n wall H from (40, 40) to (164, 40) height 108 // ends 4 (\xBD\xB78) PAST the corner\n wall V from (160, 40) to (160, 160) height 108 // butts into H\'s overlapped body\n ```\n\n (Room walls handle their own corners; this only applies to `wall \u2026 from \u2026 to \u2026`.)\n\n## Objects \u2014 circulation & fittings\n\n```wdl\nstaircase [name "N"] at (start_x, start_y) step (rise, tread, width)\n direction north|south|east|west\n [total_height <h>] [max_run <r>] [landing_depth <d>]\n [landing_thickness <t>] [turn clockwise|anticlockwise] [flight_gap <g>]\n\nkitchen [name "N"] path ((x,y), (x,y), \u2026) side left|right\n depth <d> height <h> [base_z <z>] // path points are literal numbers\n```\n\n**Staircases are TOP-anchored \u2014 this is the #1 mistake.** You put a staircase on the\n**UPPER** floor and it **DESCENDS** to the floor below:\n\n- `at (x,y)` is the **TOP** of the stair (where it meets the floor it\'s declared on).\n- `direction` is the **descent** direction (the way it travels going *down*).\n- `total_height` is the **drop** to the floor below (omit \u2192 the floor-below\'s height).\n- `max_run` caps a flight\'s run; exceed it and the stair auto-splits into switchback\n flights with turn landings (`landing_depth`/`turn`/`flight_gap` tune the switchback).\n\nSo a stair connecting the ground floor **up** to the first floor lives on the **First\nFloor**, descending to the ground:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // top = this floor, at the landing\n direction south total_height 116 // descends south to the floor below\n}\n```\n\nPut it on the *lower* floor (thinking of it as "climbing up") and it descends the wrong way\n\u2014 **below ground** \u2014 where it draws in 2D plans but is buried/invisible in 3D. `check.sh`\ncatches that (convention **C5**), but author it top-anchored from the start.\n\n// three ways to name the GLB, in order of preference:\nitem [name "N"] f."sofa" // 1. from an imported module (see Imports)\nitem [name "N"] "sofa" // 2. a same-file / bare-imported `asset` id\nitem [name "N"] asset { id "sofa" src "\u2026/sofa.glb" dims (w,h,d) [category "\u2026"] } // 3. inline one-off\n at (x,y) [rotation <deg>] [scale <s>]\n [anchor_to "RoomName" anchor center gap (gx,gy)]\n```\n\nPrefer the module form (`item f."bed_double"`) \u2014 `import "std-furniture" as f`\nonce and every piece is a short id, no URLs. The bare form (`item "sofa"`) needs\na matching top-level `asset "sofa" \u2026` in the file (or a bare `import`). The inline\n`asset { \u2026 }` block is only for a one-off GLB not in any pack. All three produce\nthe identical `{id,src,dims}` downstream. Furniture `dims` are the real-world size\nin **metres** `(width, height, depth)`; `src` is a GLB URL (an unreachable GLB\nshows a placeholder box, never a blank). `anchor` is one of `top-left top-center\ntop-right center-left center center-right bottom-left bottom-center bottom-right`.\n\n**Orientation \u2014 this is how you point furniture the right way.** A piece\'s FRONT\n(the side you sit at / the doors / the open side) faces a known compass direction\nper its `rotation` (degrees):\n\n| `rotation` | front faces |\n|---|---|\n| `0` | **South** (the plot front / entrance side, +Y) |\n| `90` | East |\n| `180` | North |\n| `270` | West |\n\nSo a sofa against the NORTH wall (facing into the room, i.e. south) is `rotation\n0`; against the SOUTH wall (facing north) it\'s `rotation 180`; against the WEST\nwall (facing east) `rotation 90`. The floor plan (`wadi_preview plans`) draws a\nsmall triangle on each piece\'s front edge so you can verify the way it points;\nfor a definitive 3D check use `wadi_capture_3d({ room: "\u2026" })` (first-person from\ninside the room).\n\n**Anchoring auto-orients.** When you `anchor` a piece to a wall and DON\'T give a\n`rotation`, it automatically faces away from that wall, into the room \u2014 `anchor\ntop-center` \u2192 faces south, `bottom-center` \u2192 north, `center-left` \u2192 east,\n`center-right` \u2192 west (a corner uses its north/south edge). So `item f."bed_double"\nanchor top-center` needs no rotation. An explicit `rotation` always overrides,\nand the derived value is written into the resolved model, so the plan notch and\nthe 3D view show it \u2014 anchoring never changes facing silently.\n\n## Imports & modules (reusable `.wdl` libraries)\n\nA `.wdl` file can be a **module** \u2014 top-level declarations (no `house` needed) \u2014\nthat another file `import`s. Two bundled ones: `std-furniture` (asset pack \u2192\n`item ns."id"`) and `konkan/base` (goal-tagged component pack \u2192 `use ns.Comp`;\nStairwell, Verandah, Otla, Bathroom, Kitchen, TulsiVrindavan, Parapet). The\n`konkan_cottage` example (`wadi_examples`) assembles a whole house from both.\n\n```wdl\nhouse Home {\n import "std-furniture" as f // aliased: refer to its assets as f."<id>"\n // import "std-furniture" // bare: its ids drop into scope for item "<id>"\n floor 1 "G" slab_thickness 0 {\n room Bed at (20,20) size (160,200) { wall north east south west\n item f."bed_double" anchor center }\n }\n}\n```\n\nA module file itself is just top-level `asset` (later: `component`) decls:\n\n```wdl\n// my-furniture.wdl \u2014 a house-less module (a reusable library)\nasset "daybed" src "https://\u2026/daybed.glb" dims (1.8, 0.4, 0.9) name "Daybed" category "Living"\n```\n\nOver MCP, `wadi_modules` lists importable modules and `wadi_module "<name>"`\nshows a module\'s asset ids + dimensions (filter with a `query`). Import refs\nresolve by name against the bundled `std-*` packs (a local `modules/` search\npath and git refs come later).\n\n## Objects \u2014 roof (one object; flat / shed / gable / hip)\n\nThe roof lives ALONE on its own top floor and you never set its Z (see\n`roof-v2-guide.md`). `endpoint`: `closed` = hip triangle, `open` = gable end-wall.\n\n```wdl\nroof [name "N"] pitched|shed|flat\n [endpoint open|closed]\n [slope angle <deg> | slope height <ridge_h>]\n [overhang <o>] [slab_thickness <t>] [parapet <h> x <t>] [gable_wall_thickness <t>] {\n segment "id" from (x,y) to (x,y) width <w>\n [high_side left|right] // shed only\n [start_endpoint open|closed] [end_endpoint open|closed]\n [hip_setback (a,b)] [gable_overhang (a,b)] [hip_ridge_extension (a,b)]\n [overhang <o>] // uniform eave, all four sides\n [overhang_start <o>] [overhang_end <o>] // per-side along the axis (shed;\n // on a gable end = gable_overhang)\n [overhang_low <o>] [overhang_high <o>] // SHED eaves (down-slope / up-slope)\n [overhang_left <o>] [overhang_right <o>] // PITCHED eaves (left / right of ridge)\n [tie_beams N]\n truss "segId" fink|mono_pitch at (pos, pos, \u2026)\n }\n```\n\nSegment `from`/`to`/`width` and the `hip_setback`/\u2026 values accept formulas, so a\nroof scales with the plot (e.g. `width House.W`, `hip_setback (Verandah.L, Padvi.L)`).\n\n**Per-side overhang (cantilever one edge).** `overhang <o>` sets a uniform eave on\nall four sides. Any sloping roof can override a side independently \u2014 each defaults to\n`overhang`. **Along the axis:** `overhang_start` / `overhang_end` (on a shed, or a\ngable open end \u2014 there they\'re the same as `gable_overhang`; a hip end is geometric,\ntuned via `hip_setback`). **Eaves:** `overhang_low` / `overhang_high` on a **shed**\n(down-slope / up-slope); `overhang_left` / `overhang_right` on a **pitched** roof\n(the two eaves either side of the ridge). A bigger eave overhang also drops that\neave\'s edge along the same pitch, so the slope stays planar. (Per-eave on a *pitched*\nroof is single-segment only \u2014 on a multi-segment roof the eaves share one height so\njoints line up.)\nIdiom: keep the roof FOOTPRINT (its supported edges) on the main room, then cantilever\none eave to cover an entry landing / stair \u2014 end the axis on the room wall and set a big\n`overhang_end`:\n```wdl\n// footprint ends on the main room\'s east wall (x204 centreline \u2192 x208 outer);\n// the east eave reaches 258, covering a landing that sticks out to x256.\nsegment "seg0" from (4,124) to (204,124) width 240 high_side right overhang 25 overhang_end 50\n```\n\n**Roof coordinates are wall centrelines (under `convention center`), same as\nrooms.** `from`/`to` is the segment\'s ridge/axis and `width` its span *centred on\nthat axis*. Author them on the **same centreline grid as the walls** \u2014 a segment\nwhose axis + width match the rooms\' centrelines auto-grows to the **outer wall\nface** on every side (the compiler extends the axis by \xBD\xB7wall_thickness at each end\nand widens by wall_thickness, exactly the grow a room gets). `overhang` then\nextends *beyond* the outer face. So to cover a footprint spanning wall centrelines\n`x1..x2` (E\u2013W) and `yA..yB` (N\u2013S), write `from (x1, (yA+yB)/2) to (x2, (yA+yB)/2)\nwidth (yB - yA)` \u2014 do **not** add \xBD-wall fudge factors; the convention handles it.\n(Before this, a roof drawn on the grid sat half a wall-thickness *inside* the walls.)\n\n## Components & layers\n\n```wdl\ncomponent Bench { // a reusable mini-house in LOCAL coords (origin 0,0)\n param blen = 60 label "Bench length"\n beam name "Top" at (0,0) size (blen, 18) height 6\n}\nuse Bench as "B1" at (x,y) with { blen = 80 } // stamp it onto a floor\n\nlayer "structure" "Structure" [color "#rrggbb"] [group "Frame"] // per-house layer registry\n```\n\nA component may carry a **`goal`** \u2014 a short description of what it accomplishes,\nthe discovery key for module lookup (`wadi_module` / a `wadi_modules` query):\n\n```wdl\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116\n staircase name "Stair" at (0,0) step (7,11,44) direction south total_height rise\n}\n```\n\nComponents can also come from an **imported module** (see *Imports & modules*),\nstamped with a namespaced `use ns.Comp`:\n\n```wdl\nhouse Home {\n import "konkan/base" as kb // Stairwell, Verandah, Otla (goal-tagged)\n floor 1 "G" slab_thickness 0 {\n room Hall at (20,20) size (200,200) { wall north east south west }\n use kb.Stairwell at (60,60) with { rise = 116 } // param args use `=`, not `:`\n }\n}\n```\n\n`use ns.Comp` expands byte-identical to an inline `component`; keep module\ncomponents flat (they don\'t `use` other components). Un-overridden `param`s fall\nback to their declared defaults.\n\n## The `raw` escape (rarely needed)\n\nAnything the first-class syntax doesn\'t cover can be written as literal JSON per\nthe `.wadi` schema (`data-model.md`):\n\n```wdl\nraw "type" { "field": 1, "formulas": { "field": "= expr" } }\n```\n\n## DSL-specific pitfalls\n\n- **`convention center` and `units \u2026 per_unit 10`** belong at the top of every\n `house` \u2014 same as the JSON path. All the `coordinate-system.md` rules (Y-down,\n units, centreline abutment) apply identically; the DSL just writes them shorter.\n- **Formulas are bare expressions**, not `"= \u2026"` strings \u2014 the compiler emits the\n `= \u2026` form for you. Write `at (main.x1, main.yA)`, not `at ("= main.x1", \u2026)`.\n- **`name "\u2026"` is quoted; `room`/`pillar`/`var`/grid-line names are bare** ids\n (no spaces, and not a reserved word like `width`, `height`, `size`, `at`).\n- **Roof alone on the top floor**; segment widths/positions come from the walls\n they sit on. See `roof-v2-guide.md`.\n- **A pillar\'s `at` is its TOP-LEFT corner, not its centre.** To centre a column on\n `(cx,cy)`, author `at (cx - w/2, cy - l/2)`.\n- **Free-standing walls don\'t auto-mitre at corners** \u2014 extend endpoints so the wall\n bodies overlap (\u2265 \xBD\xB7`wall_thickness` past the shared point), or the corner is left\n as a gap.\n- **Staircases are top-anchored** \u2014 put them on the UPPER floor; they descend to the\n floor below (`check.sh` C5 flags one that lands below ground). See the staircase note.\n- **Structural conventions are enforced** \u2014 `check.sh` fails on floating floors\n (plinth-floor `height` \u2260 plinth block height; a no-slab floor with nonzero\n `slab_thickness`) and warns on exterior room sides left open. See\n `conventions.md`; the DSL editor shows the same findings in its status pill.\n- Compile after **every** edit; a parse error means the `.wadi` wasn\'t updated, so\n the live model just won\'t change \u2014 never silently wrong.\n'
419002
+ "body": '# The Wadi DSL (`.wdl`) \u2014 authoring reference\n\nYou author houses in the **Wadi DSL** \u2014 a small, formal language (`.wdl`) that\ncompiles to a resolved `.wadi` (`house_config.json`). The DSL is **complete**:\nevery object type in the model has first-class syntax, so you rarely need the\n`raw` escape. Authoring the DSL is more direct and less error-prone than writing\nJSON \u2014 the grammar enforces structure, and `check.sh` reports parse errors with\nline:col.\n\n**This file is the SYNTAX reference.** The *semantics* live in the other\nreferences and apply unchanged \u2014 read them:\n\n- `coordinate-system.md` \u2014 X\u2192right, **Y\u2192DOWN**, Z\u2192up; **10 units = 1 ft**;\n the **centreline** convention. The #1 source of mistakes.\n- `conventions.md` \u2014 the **structural coding conventions** (`check.sh` enforces\n them): plinth-floor height must match the plinth block, rooms must wall every\n exterior side, a no-slab floor must set `slab_thickness 0`.\n- `parametric-conventions.md` \u2014 the grid-first recipe for reusable templates.\n- `roof-v2-guide.md` \u2014 roof segments, hip vs gable, trusses, joints.\n- `data-model.md` \u2014 the underlying `.wadi` schema (what the DSL compiles to; also\n the field reference for the `raw` escape).\n\n## The loop\n\n1. Write / edit `house.wdl` \u2014 the **single shared source** (you and the human\n co-edit it; the app\'s DSL previewer renders it live). You never produce a `.wadi`.\n2. `wadi-skill/architect/scripts/check.sh house.wdl` \u2014 runs the DSL compiler +\n validator (schema + wall/roof geometry) against a **throwaway temp** just for\n feedback; fix any reported error and re-run.\n3. `preview.sh house.wdl` \u2192 read the PNGs (plans / elevations / roof) to check your\n work. (It also compiles to a throwaway temp \u2014 no persistent `.wadi`.)\n\n## Skeleton\n\n```wdl\nhouse MyHouse {\n convention center // ALWAYS use center (wall-centreline coords)\n units feet_inches per_unit 10 // 10 project units = 1 ft\n site { plot (WIDTH, LENGTH) ref (0, 0) }\n defaults { floor_height 120 wall_height 108 slab_thickness 8 wall_thickness 8 }\n\n // parametric core (optional): var, point, grid, configurator\n // component / layer declarations (optional)\n floor 0 "Plinth" { \u2026 } // floors stack in source order (0 = plinth)\n floor 1 "Ground Floor" { \u2026 }\n floor 2 "Loft" { roof \u2026 } // roof lives ALONE on its own top floor\n}\n```\n\nNumbers are **project units** (feet \xD7 10 by default). Names after `house`,\n`room`, `pillar`, `var`, `point`, `grid`, and `use`/`component` are bare\nidentifiers (no spaces); names introduced with the `name` keyword are quoted\nstrings.\n\n## Parametric core (domain-neutral)\n\n```wdl\nvar wallT = 8 // a knob; may reference other vars\nvar pilInset = (pillarW - wallT) / 2\n\npoint House { x = 420, y = 470 } // reference as House.x / House.W / House.L\n // (.W = x, .L = y \u2014 a point doubles as a size)\n\ngrid main { // named wall centrelines; publishes main.x1 / main.yA\n x: 1 @ wallT / 2, 2 @ House.W / 2, 3 @ House.W - wallT / 2\n y: A @ wallT / 2, B @ House.L / 2, C @ House.L - wallT / 2\n}\n// each line may add: \u2026 @ <expr> thick <expr> role structural|planning\n\nconfigurator { // the owner-facing template you author\n title "Configure your home" // panel heading (optional)\n note "Everything re-flows to fit." // panel subtitle (optional)\n\n slider pillarW "Column size" ft [8 .. 14 step 1] note "help text" // trailing note optional\n number ceiling "Ceiling height" ft\n toggle has_loft "Add a loft"\n select roof_style "Roof style" { Flat = 0, Shed = 1, Gable = 2, Hip = 3 }\n select floorH "Ceiling height" { "9 ft" = 90, "10 ft (std)" = 100 } // labels can be quoted strings\n\n group "Plot" note "about this section" { // sections the panel; label only\n slider W "Plot width" ft [340 .. 520 step 10]\n }\n}\n```\n\nEvery knob binds to a `var` by name (`target`). To expose a plot dimension, model\nit as a `var` and reference it from the point (`point House { x = W }`), then bind\nthe knob to `W` \u2014 knobs target vars, never a point field like `House.W`.\n\n**Formulas are automatic.** Any geometry number can be a formula \u2014 just write the\nexpression instead of a literal (`at (main.x1, main.yA)`, `size (House.W/2, 200)`).\nOperators: `+ - * /`, unary `-`, parentheses, and the functions\n`min max clamp round floor ceil abs`. References: a `var`, a `point`\n(`House.W`), or a grid line (`main.x3 - main.x1`). No comparison operators \u2014 gate\nthings with the `min/abs` idiom (see `enabled` below).\n\n## Common attribute tail (every object)\n\nAfter an object\'s geometry, in THIS order, any of:\n\n```\n\u2026 z_offset <expr> enabled <expr> layer "id" [material "id"]\n```\n\n- `enabled <expr>` \u2014 the on/off switch. A `0`/`false` value hides the object. To\n gate on a configurator variable, use a 0/1 formula:\n `enabled 1 - min(1, abs(roof_style - 3))` renders the object only when\n `roof_style == 3`. (This is how one template carries several roofs and shows\n only the chosen one.)\n- `z_offset <expr>` \u2014 lift above the floor base (split levels).\n- `material "id"` \u2014 only on plinth / ground / room / wall / staircase / kitchen /\n roof.\n\n## Objects \u2014 structure & envelope\n\n```wdl\nslab [name "N"] at (x,y) size (w,l) [thickness <t>] // floor_slab\nbeam [name "N"] at (x,y) size (w,l) [height <h>]\nplinth [name "N"] at (x,y) size (w,l) height <h> // raised base (Plinth floor)\nground [name "N"] at (x,y) size (w,l) [height <h>] // terrain plane\npillar Name at (x,y) size (w,l) [height <h>] // (x,y) = TOP-LEFT corner\n```\n\n`at (x,y)` is the **TOP-LEFT CORNER** \u2014 **not the centre** \u2014 for every one of these\n(same as rooms/slabs/beams); `size (w,l)` is width \xD7 length. All accept the common tail.\n\n**Pillars catch people out here.** A column reads as "placed at a point," but `at` is\nstill its corner. To **centre a column on a point** `(cx, cy)` \u2014 a grid node, a room\ncorner \u2014 place it at **`at (cx - w/2, cy - l/2)`**, never at `(cx, cy)`. On a grid, the\n`pilInset` idiom (see `parametric-conventions.md`) does exactly this so columns sit flush.\n\n## Objects \u2014 rooms, walls & openings\n\nA room shows exactly the walls you declare. A **bare room (no `wall` lines) is\nenclosed on all four sides.** List plain walls compactly; give a wall its own line\nonly when it carries a door/window; omit a side to leave it open (verandah).\n\n```wdl\nroom Name at (x,y) size (w,l) [height <h>] [material "\u2026"] {\n wall east west north // plain walls \u2014 several in one statement\n wall south { door Main at <offset> size (w,h) [open] } // wall WITH openings: one side\n wall west { window W at <offset> size (w,h) [sill <s>] [open] }\n item asset { \u2026 } anchor center [gap (gx,gy)] // furniture anchored inside the room\n}\n```\n\n- `wall <side>\u2026` sides are `north|south|east|west`. A `wall <side>` line may also\n add `height <h>` / `height_end <h>` (sloped).\n- `door`/`window` `at <offset>` is measured along the wall from its start;\n `size (width, height)`; `window \u2026 sill <s>` sets the sill height; `open` = a bare\n hole (no leaf/glazing).\n\nA **free-standing wall** (not a room side):\n\n```wdl\nwall Name from (x1,y1) to (x2,y2) [height <h>] [height_end <h>] [facing north|\u2026] {\n \u2026 door/window openings \u2026\n}\n```\n\n- `from`/`to` are the wall\'s **centreline** endpoints; the wall is drawn as a rectangle\n `wall_thickness` wide, centred on that line.\n- **Overlap walls at corners \u2014 they do NOT auto-mitre.** Two free-standing walls that\n merely *touch* at a shared endpoint leave an unfilled square notch (\xBD\xB7`wall_thickness`)\n at the corner, because each is just a rectangle capped at its endpoint. To fill the\n corner, **extend the endpoints so the wall bodies OVERLAP** \u2014 run at least one wall\'s\n end **half the wall thickness past** the shared point (overlapping by the full thickness\n is fine and simplest). For an L of thickness 8 meeting at `(160,40)`:\n\n ```wdl\n wall H from (40, 40) to (164, 40) height 108 // ends 4 (\xBD\xB78) PAST the corner\n wall V from (160, 40) to (160, 160) height 108 // butts into H\'s overlapped body\n ```\n\n (Room walls handle their own corners; this only applies to `wall \u2026 from \u2026 to \u2026`.)\n\n## Objects \u2014 circulation & fittings\n\n```wdl\nstaircase [name "N"] at (start_x, start_y) step (rise, tread, width)\n direction north|south|east|west\n [total_height <h>] [max_run <r>] [landing_depth <d>]\n [landing_thickness <t>] [turn clockwise|anticlockwise] [flight_gap <g>]\n\nkitchen [name "N"] path ((x,y), (x,y), \u2026) side left|right\n depth <d> height <h> [base_z <z>] // path points are literal numbers\n```\n\n**Staircases are TOP-anchored \u2014 this is the #1 mistake.** You put a staircase on the\n**UPPER** floor and it **DESCENDS** to the floor below:\n\n- `at (x,y)` is the **TOP** of the stair (where it meets the floor it\'s declared on).\n- `direction` is the **descent** direction (the way it travels going *down*).\n- `total_height` is the **drop** to the floor below (omit \u2192 the floor-below\'s height).\n- `max_run` caps a flight\'s run; exceed it and the stair auto-splits into switchback\n flights with turn landings (`landing_depth`/`turn`/`flight_gap` tune the switchback).\n\nSo a stair connecting the ground floor **up** to the first floor lives on the **First\nFloor**, descending to the ground:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // top = this floor, at the landing\n direction south total_height 116 // descends south to the floor below\n}\n```\n\nPut it on the *lower* floor (thinking of it as "climbing up") and it descends the wrong way\n\u2014 **below ground** \u2014 where it draws in 2D plans but is buried/invisible in 3D. `check.sh`\ncatches that (convention **C5**), but author it top-anchored from the start.\n\n// three ways to name the GLB, in order of preference:\nitem [name "N"] f."sofa" // 1. from an imported module (see Imports)\nitem [name "N"] "sofa" // 2. a same-file / bare-imported `asset` id\nitem [name "N"] asset { id "sofa" src "\u2026/sofa.glb" dims (w,h,d) [category "\u2026"] } // 3. inline one-off\n at (x,y) [rotation <deg>] [scale <s>]\n [anchor_to "RoomName" anchor center gap (gx,gy)]\n```\n\nPrefer the module form (`item f."bed_double"`) \u2014 `import "std-furniture" as f`\nonce and every piece is a short id, no URLs. The bare form (`item "sofa"`) needs\na matching top-level `asset "sofa" \u2026` in the file (or a bare `import`). The inline\n`asset { \u2026 }` block is only for a one-off GLB not in any pack. All three produce\nthe identical `{id,src,dims}` downstream. Furniture `dims` are the real-world size\nin **metres** `(width, height, depth)`; `src` is a GLB URL (an unreachable GLB\nshows a placeholder box, never a blank). `anchor` is one of `top-left top-center\ntop-right center-left center center-right bottom-left bottom-center bottom-right`.\n\n**Orientation \u2014 this is how you point furniture the right way.** A piece\'s FRONT\n(the side you sit at / the doors / the open side) faces a known compass direction\nper its `rotation` (degrees):\n\n| `rotation` | front faces |\n|---|---|\n| `0` | **South** (the plot front / entrance side, +Y) |\n| `90` | East |\n| `180` | North |\n| `270` | West |\n\nSo a sofa against the NORTH wall (facing into the room, i.e. south) is `rotation\n0`; against the SOUTH wall (facing north) it\'s `rotation 180`; against the WEST\nwall (facing east) `rotation 90`. The floor plan (`wadi_preview plans`) draws a\nsmall triangle on each piece\'s front edge so you can verify the way it points;\nfor a definitive 3D check use `wadi_capture_3d({ room: "\u2026" })` (first-person from\ninside the room).\n\n**Anchoring auto-orients.** When you `anchor` a piece to a wall and DON\'T give a\n`rotation`, it automatically faces away from that wall, into the room \u2014 `anchor\ntop-center` \u2192 faces south, `bottom-center` \u2192 north, `center-left` \u2192 east,\n`center-right` \u2192 west (a corner uses its north/south edge). So `item f."bed_double"\nanchor top-center` needs no rotation. An explicit `rotation` always overrides,\nand the derived value is written into the resolved model, so the plan notch and\nthe 3D view show it \u2014 anchoring never changes facing silently.\n\n## Imports & modules (reusable `.wdl` libraries)\n\nA `.wdl` file can be a **module** \u2014 top-level declarations (no `house` needed) \u2014\nthat another file `import`s. Two bundled ones: `std-furniture` (asset pack \u2192\n`item ns."id"`) and `konkan/base` (goal-tagged component pack \u2192 `use ns.Comp`;\nStairwell, Verandah, Otla, Bathroom, Kitchen, TulsiVrindavan, Parapet). The\n`konkan_cottage` example (`wadi_examples`) assembles a whole house from both.\n\n```wdl\nhouse Home {\n import "std-furniture" as f // aliased: refer to its assets as f."<id>"\n // import "std-furniture" // bare: its ids drop into scope for item "<id>"\n floor 1 "G" slab_thickness 0 {\n room Bed at (20,20) size (160,200) { wall north east south west\n item f."bed_double" anchor center }\n }\n}\n```\n\nA module file itself is just top-level `asset` (later: `component`) decls:\n\n```wdl\n// my-furniture.wdl \u2014 a house-less module (a reusable library)\nasset "daybed" src "https://\u2026/daybed.glb" dims (1.8, 0.4, 0.9) name "Daybed" category "Living"\n```\n\nOver MCP, `wadi_modules` lists importable modules and `wadi_module "<name>"`\nshows a module\'s asset ids + dimensions (filter with a `query`). Import refs\nresolve by name against the bundled `std-*` packs (a local `modules/` search\npath and git refs come later).\n\n## Objects \u2014 roof (one object; flat / shed / gable / hip)\n\nThe roof lives ALONE on its own top floor and you never set its Z (see\n`roof-v2-guide.md`). `endpoint`: `closed` = hip triangle, `open` = gable end-wall.\n\n```wdl\nroof [name "N"] pitched|shed|flat\n [endpoint open|closed]\n [slope angle <deg> | slope height <ridge_h>] // symmetric pitch (one value)\n [slope angle (<left>, <right>)] // asymmetric (saltbox) gable \u2014 angle pair\n [overhang <o>] [slab_thickness <t>] [parapet <h> x <t>] [gable_wall_thickness <t>] {\n segment "id" from (x,y) to (x,y) width <w>\n [high_side left|right] // shed only\n [start_endpoint open|closed] [end_endpoint open|closed]\n [hip_setback (a,b)] [gable_overhang (a,b)] [hip_ridge_extension (a,b)]\n [overhang <o>] // uniform eave, all four sides\n [overhang_start <o>] [overhang_end <o>] // per-side along the axis (shed;\n // on a gable end = gable_overhang)\n [overhang_low <o>] [overhang_high <o>] // SHED eaves (down-slope / up-slope)\n [overhang_left <o>] [overhang_right <o>] // PITCHED eaves (left / right of ridge)\n [tie_beams N]\n truss "segId" fink|mono_pitch at (pos, pos, \u2026)\n }\n```\n\nSegment `from`/`to`/`width` and the `hip_setback`/\u2026 values accept formulas, so a\nroof scales with the plot (e.g. `width House.W`, `hip_setback (Verandah.L, Padvi.L)`).\n\n**Per-side overhang (cantilever one edge).** `overhang <o>` sets a uniform eave on\nall four sides. Any sloping roof can override a side independently \u2014 each defaults to\n`overhang`. **Along the axis:** `overhang_start` / `overhang_end` (on a shed, or a\ngable open end \u2014 there they\'re the same as `gable_overhang`; a hip end is geometric,\ntuned via `hip_setback`). **Eaves:** `overhang_low` / `overhang_high` on a **shed**\n(down-slope / up-slope); `overhang_left` / `overhang_right` on a **pitched** roof\n(the two eaves either side of the ridge). A bigger eave overhang also drops that\neave\'s edge along the same pitch, so the slope stays planar. (Per-eave on a *pitched*\nroof is single-segment only \u2014 on a multi-segment roof the eaves share one height so\njoints line up.)\n\n**Asymmetric gable (saltbox) \u2014 an angle pair.** A pitched roof\'s `slope` gives both\nfaces the same pitch (a symmetric gable). To make the two sides different, give\n`slope angle` a **pair** instead of one value \u2014 `slope angle (45, 25)`. A single value\nis symmetric; a pair is asymmetric, and that\'s the whole distinction (no separate\nkeywords, nothing half-settable). The two eaves stay put (footprint unchanged) and the\nridge shifts across the width so each face takes its angle; the gable-end triangle and\ntrusses follow. The pair is `(left, right)` by the segment\'s left normal \u2014 the **same\nsides as** `overhang_left`/`overhang_right`. Angles are measured to the wall-top eave\nline. `height` is single-value only (both faces share one ridge line). Intended for a\nsingle-segment gable (`endpoint open`); on a hip end the ridge shift skews the hip.\n\n```wdl\nroof pitched endpoint open slope angle (45, 25) {\n segment "s0" from (House.W/2, 0) to (House.W/2, House.L) width House.W\n}\n```\nIdiom: keep the roof FOOTPRINT (its supported edges) on the main room, then cantilever\none eave to cover an entry landing / stair \u2014 end the axis on the room wall and set a big\n`overhang_end`:\n```wdl\n// footprint ends on the main room\'s east wall (x204 centreline \u2192 x208 outer);\n// the east eave reaches 258, covering a landing that sticks out to x256.\nsegment "seg0" from (4,124) to (204,124) width 240 high_side right overhang 25 overhang_end 50\n```\n\n**Roof coordinates are wall centrelines (under `convention center`), same as\nrooms.** `from`/`to` is the segment\'s ridge/axis and `width` its span *centred on\nthat axis*. Author them on the **same centreline grid as the walls** \u2014 a segment\nwhose axis + width match the rooms\' centrelines auto-grows to the **outer wall\nface** on every side (the compiler extends the axis by \xBD\xB7wall_thickness at each end\nand widens by wall_thickness, exactly the grow a room gets). `overhang` then\nextends *beyond* the outer face. So to cover a footprint spanning wall centrelines\n`x1..x2` (E\u2013W) and `yA..yB` (N\u2013S), write `from (x1, (yA+yB)/2) to (x2, (yA+yB)/2)\nwidth (yB - yA)` \u2014 do **not** add \xBD-wall fudge factors; the convention handles it.\n(Before this, a roof drawn on the grid sat half a wall-thickness *inside* the walls.)\n\n## Components & layers\n\n```wdl\ncomponent Bench { // a reusable mini-house in LOCAL coords (origin 0,0)\n param blen = 60 label "Bench length"\n beam name "Top" at (0,0) size (blen, 18) height 6\n}\nuse Bench as "B1" at (x,y) [rotation <deg>] with { blen = 80 } // stamp onto a floor\n\nlayer "structure" "Structure" [color "#rrggbb"] [group "Frame"] // per-house layer registry\n```\n\nA component may carry a **`goal`** \u2014 a short description of what it accomplishes,\nthe discovery key for module lookup (`wadi_module` / a `wadi_modules` query):\n\n```wdl\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116\n staircase name "Stair" at (0,0) step (7,11,44) direction south total_height rise\n}\n```\n\nComponents can also come from an **imported module** (see *Imports & modules*),\nstamped with a namespaced `use ns.Comp`:\n\n```wdl\nhouse Home {\n import "konkan/base" as kb // Stairwell, Verandah, Otla (goal-tagged)\n floor 1 "G" slab_thickness 0 {\n room Hall at (20,20) size (200,200) { wall north east south west }\n use kb.Stairwell at (60,60) with { rise = 116 } // param args use `=`, not `:`\n }\n}\n```\n\n`use ns.Comp` expands byte-identical to an inline `component`. Components **nest\nfreely**: a library component may `use` a sibling, `use` a component from a\nlibrary it itself `import`s, and place `item ns."id"` furniture from its own\nimports \u2014 imports resolve **transitively** (cycles are a compile error).\nUn-overridden `param`s fall back to their declared defaults.\n\n`rotation <deg>` (optional, yaw\xB0: 0=south, 90=east) turns the whole stamped\nassembly about its origin. **Right angles (0/90/180/270) are exact for any\ncomponent** (rooms/pillars/beams/slabs swap dims + remap wall sides; furniture\nturns with them). A **non-right angle** is allowed **only for a furniture-only\ncomponent** (items/free walls rotate to any angle); a free angle on a component\nthat contains a room/pillar/beam/slab/staircase is a compile error (arbitrary\nstructural rotation is a future feature).\n\n## The `raw` escape (rarely needed)\n\nAnything the first-class syntax doesn\'t cover can be written as literal JSON per\nthe `.wadi` schema (`data-model.md`):\n\n```wdl\nraw "type" { "field": 1, "formulas": { "field": "= expr" } }\n```\n\n## DSL-specific pitfalls\n\n- **`convention center` and `units \u2026 per_unit 10`** belong at the top of every\n `house` \u2014 same as the JSON path. All the `coordinate-system.md` rules (Y-down,\n units, centreline abutment) apply identically; the DSL just writes them shorter.\n- **Formulas are bare expressions**, not `"= \u2026"` strings \u2014 the compiler emits the\n `= \u2026` form for you. Write `at (main.x1, main.yA)`, not `at ("= main.x1", \u2026)`.\n- **`name "\u2026"` is quoted; `room`/`pillar`/`var`/grid-line names are bare** ids\n (no spaces, and not a reserved word like `width`, `height`, `size`, `at`).\n- **Roof alone on the top floor**; segment widths/positions come from the walls\n they sit on. See `roof-v2-guide.md`.\n- **A pillar\'s `at` is its TOP-LEFT corner, not its centre.** To centre a column on\n `(cx,cy)`, author `at (cx - w/2, cy - l/2)`.\n- **Free-standing walls don\'t auto-mitre at corners** \u2014 extend endpoints so the wall\n bodies overlap (\u2265 \xBD\xB7`wall_thickness` past the shared point), or the corner is left\n as a gap.\n- **Staircases are top-anchored** \u2014 put them on the UPPER floor; they descend to the\n floor below (`check.sh` C5 flags one that lands below ground). See the staircase note.\n- **Structural conventions are enforced** \u2014 `check.sh` fails on floating floors\n (plinth-floor `height` \u2260 plinth block height; a no-slab floor with nonzero\n `slab_thickness`) and warns on exterior room sides left open. See\n `conventions.md`; the DSL editor shows the same findings in its status pill.\n- Compile after **every** edit; a parse error means the `.wadi` wasn\'t updated, so\n the live model just won\'t change \u2014 never silently wrong.\n'
418021
419003
  },
418022
419004
  "conventions": {
418023
419005
  "title": "Structural coding conventions (C1/C2/C3\u2026)",
418024
- "body": '# Wadi structural conventions (coding guidelines)\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026) so this document and the\nlinter stay in lockstep. Add a rule by adding a check to `lintStructure` **and** a\nsection here with the next id.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor\'s base elevation = the running sum of the previous floors\' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor\'s walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor\'s height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set\nan explicit `height`, and that height must equal the plinth block\'s `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth\nblock rises to `plinth.height`. If they differ, the floor above floats above the\nplinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor\n`height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 "Plinth" height 40 { // == the plinth block height below\n ground name "Ground" at (0,0) size (500,500)\n plinth name "Plinth" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is\nconsistent by construction \u2014 but set the floor `height` explicitly anyway, so the\nstack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every\nside that faces **outside** (no room beyond it). Interior (shared) sides may be\nomitted \u2014 the neighbour\'s wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no\n`wall` lines) is enclosed on all four sides**. But the moment you add a `wall`\nline to hang a door or window, the room switches to a *whitelist* \u2014 every side you\ndon\'t list is now a hole. An exterior hole leaves the room open to the weather.\nThis is the #1 footgun the conventions guard against.\n\nIt is a **warning**, not an error, because an open exterior side is sometimes\nintentional (a verandah / open padvi). If it is deliberate, leave it \u2014 the warning\ndocuments the choice. Otherwise, add the wall.\n\n**Fix.** List the plain exterior walls compactly alongside the opening walls:\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n*(The check samples several points along each side, so a side sheltered by rooms\nabove is correctly treated as interior, not open. It also skips a side that\nalready has a wall on its line \u2014 one declared by an adjacent or overlapping room,\nor a standalone wall \u2014 so a shared exterior wall the neighbour declares is not\ndouble-flagged.)*\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object**\nmust set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor\'s walls stand on\n(`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is\nno deck, so every wall on the floor floats `slab_thickness` units above the floor\nbase. Setting it to `0` puts the walls on the floor base; alternatively, model the\ndeck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 "Ground" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor\nof just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is\nharmless.)*\n\n---\n\n## C4 \u2014 A stacked floor\'s height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set\n`height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor\'s walls stand on the\ndeck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor\nabove leaves a gap over the walls; when smaller, the walls poke through it. (These three\nfields are otherwise independent \u2014 see the vertical model above.) It is a **warning** \u2014 a\ndeliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they\nshould match.\n\n**Fix.** Make them add up, most simply via the house defaults:\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing\nstacks on its walls.)*\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase\'s descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Staircases are **top-anchored**: you place one on the **upper** floor and it\n**descends** to the floor below (`at` is the top, `direction` is the descent, `total_height`\nis the drop). Put it on the *lower* floor (as if climbing up), or give it too large a\n`total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D\nplans (which ignore Z) but is **buried and invisible in 3D**, with no other error. This is\nthe one that bit a real design: a stair on the ground floor "climbing" to the first floor\nwas expanded to `z_offset: -105` and vanished from the 3D view.\n\n**Fix.** Move the staircase **up one floor** and let it descend. The stair that connects the\nground floor to the first floor lives on the **First Floor**:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // `at` = the TOP (this floor)\n direction south total_height 116 // descends to the floor below\n}\n```\n\n*(See the staircase section of `dsl.md` for the full top-anchored convention.)*\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Planned conventions (not yet enforced)\n\nDocumented so authors know they matter; not linted yet:\n\n- **Interior partition gaps** \u2014 where two rooms share a centreline and *neither*\n declares that wall, there is no partition between them. (C2 only covers\n *exterior* sides.)\n- **Slab thickness \u2194 slab object** \u2014 when a floor *does* carry a `floor_slab`,\n its `slab_thickness` should match the slab\'s own thickness so walls sit on the\n real deck.\n- **Roof footprint coverage** \u2014 the roof segments should span the top occupied\n floor\'s footprint (no uncovered rooms).\n'
419006
+ "body": "# Wadi structural conventions (coding guidelines)\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026) so this document and the\nlinter stay in lockstep. Add a rule by adding a check to `lintStructure` **and** a\nsection here with the next id.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor's base elevation = the running sum of the previous floors' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor's walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor's height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set\nan explicit `height`, and that height must equal the plinth block's `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth\nblock rises to `plinth.height`. If they differ, the floor above floats above the\nplinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor\n`height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 \"Plinth\" height 40 { // == the plinth block height below\n ground name \"Ground\" at (0,0) size (500,500)\n plinth name \"Plinth\" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is\nconsistent by construction \u2014 but set the floor `height` explicitly anyway, so the\nstack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every\nside that faces **outside** (no room beyond it). Interior (shared) sides may be\nomitted \u2014 the neighbour's wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no\n`wall` lines) is enclosed on all four sides**. But the moment you add a `wall`\nline to hang a door or window, the room switches to a *whitelist* \u2014 every side you\ndon't list is now a hole. An exterior hole leaves the room open to the weather.\nThis is the #1 footgun the conventions guard against.\n\nIt is a **warning**, not an error, because an open exterior side is sometimes\nintentional (a verandah / open padvi). If it is deliberate, leave it \u2014 the warning\ndocuments the choice. Otherwise, add the wall.\n\n**Fix.** List the plain exterior walls compactly alongside the opening walls:\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n*(The check samples several points along each side, so a side sheltered by rooms\nabove is correctly treated as interior, not open. It also skips a side that\nalready has a wall on its line \u2014 one declared by an adjacent or overlapping room,\nor a standalone wall \u2014 so a shared exterior wall the neighbour declares is not\ndouble-flagged.)*\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object**\nmust set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor's walls stand on\n(`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is\nno deck, so every wall on the floor floats `slab_thickness` units above the floor\nbase. Setting it to `0` puts the walls on the floor base; alternatively, model the\ndeck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor\nof just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is\nharmless.)*\n\n---\n\n## C4 \u2014 A stacked floor's height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set\n`height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor's walls stand on the\ndeck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor\nabove leaves a gap over the walls; when smaller, the walls poke through it. (These three\nfields are otherwise independent \u2014 see the vertical model above.) It is a **warning** \u2014 a\ndeliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they\nshould match.\n\n**Fix.** Make them add up, most simply via the house defaults:\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing\nstacks on its walls.)*\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase's descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Staircases are **top-anchored**: you place one on the **upper** floor and it\n**descends** to the floor below (`at` is the top, `direction` is the descent, `total_height`\nis the drop). Put it on the *lower* floor (as if climbing up), or give it too large a\n`total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D\nplans (which ignore Z) but is **buried and invisible in 3D**, with no other error. This is\nthe one that bit a real design: a stair on the ground floor \"climbing\" to the first floor\nwas expanded to `z_offset: -105` and vanished from the 3D view.\n\n**Fix.** Move the staircase **up one floor** and let it descend. The stair that connects the\nground floor to the first floor lives on the **First Floor**:\n\n```wdl\nfloor 2 \"First Floor\" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name \"Stair\" at (212, 64) step (7, 11, 44) // `at` = the TOP (this floor)\n direction south total_height 116 // descends to the floor below\n}\n```\n\n*(See the staircase section of `dsl.md` for the full top-anchored convention.)*\n\n## C6 \u2014 Openings on the same wall must not overlap \xB7 **error**\n\n**Statement.** Two openings (doors/windows) cut into the **same physical wall** must not\noverlap along it. This includes openings that belong to **two different rooms sharing a\nboundary wall** \u2014 a door on Living's east side and a door on Bedroom's west side sit on the\nsame wall line and can collide.\n\n**Rationale.** Each opening is a boolean-subtract from the wall. Overlapping spans merge into\none ragged hole (or fight over the same brick), which is never what you meant \u2014 and on a\nshared wall it silently punches a bigger gap than either room's plan shows.\n\n**Fix.** Offset or narrow one opening so the spans are disjoint. Openings are measured from\nthe wall's start corner (`offset` = near edge; the opening occupies `[offset, offset+width]`).\nFor a shared wall, remember both rooms' offsets are measured along the **same** line, so a\ndoor at `offset 50 width 40` (\u2192 `[50,90]`) on one room clears a door at `offset 90` on the\nother, but not one at `offset 60`.\n\n## C7 \u2014 Furniture items should not overlap \xB7 **warning**\n\n**Statement.** Two furniture `item`s whose plan footprints overlap are flagged \u2014 as a\n**warning**, because it is sometimes intentional (a rug under a table, a lamp on a desk,\ndeliberately stacked pieces).\n\n**Rationale.** More often it's a placement slip \u2014 two beds dropped on the same spot, or an\nanchored piece that reflowed into another when a room was resized. The footprint used is the\nitem's rotated bounding box (yaw-aware), so it matches what the plan draws.\n\n**Fix.** Reposition one item, or ignore the warning if the overlap is deliberate.\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Planned conventions (not yet enforced)\n\nDocumented so authors know they matter; not linted yet:\n\n- **Interior partition gaps** \u2014 where two rooms share a centreline and *neither*\n declares that wall, there is no partition between them. (C2 only covers\n *exterior* sides.)\n- **Slab thickness \u2194 slab object** \u2014 when a floor *does* carry a `floor_slab`,\n its `slab_thickness` should match the slab's own thickness so walls sit on the\n real deck.\n- **Roof footprint coverage** \u2014 the roof segments should span the top occupied\n floor's footprint (no uncovered rooms).\n"
418025
419007
  },
418026
419008
  "coordinate-system": {
418027
419009
  "title": "Coordinates, units & the centreline convention",
@@ -418047,7 +419029,7 @@ var MODULES = {
418047
419029
  },
418048
419030
  "konkan/base": {
418049
419031
  "summary": "Goal-tagged Konkan house parts (Stairwell, Verandah, Otla) \u2014 components for `use`.",
418050
- "source": '// konkan/base.wdl \u2014 a starter pack of reusable, goal-tagged Konkan house parts.\n//\n// A MODULE (no `house` body): import it and stamp its components onto a floor \u2014\n// import "konkan/base" as kb\n// floor 1 "Ground" { use kb.Stairwell at (208, 64) with { rise: 116 } }\n//\n// Each component is authored in LOCAL coordinates (origin 0,0) and is flat\n// (it does not `use` other components), so it stamps cleanly into any host.\n// The `goal` line is the discovery key \u2014 `wadi_module "konkan/base"` (or a\n// `wadi_modules` query) surfaces the component whose goal matches the intent.\n\n// Climb one floor. A single straight run for a short rise; give `run` and the\n// staircase auto-folds into switchback flights (max_run) when the rise is tall.\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116 // total height to the floor above (= floor_height)\n param run = 200 // max horizontal run before a switchback landing\n staircase name "Stair" at (0, 0) step (7, 11, 44) direction south total_height rise max_run run\n}\n\n// A shaded sit-out running along the front of the house \u2014 the room is open to\n// the south (front) and enclosed on the other three sides. Add a roof + pillars\n// in the host if you want it covered.\ncomponent Verandah goal "a shaded sit-out along the house front" {\n param across = 200 // span across the front\n param deep = 70 // how far it projects\n room Verandah at (0, 0) size (across, deep) {\n wall north east west // open to the south\n }\n}\n\n// An otla \u2014 the traditional Konkan raised platform at the entrance where people\n// sit. A low slab you place at the doorway (its thickness is the platform rise).\ncomponent Otla goal "a raised entrance platform to sit on (Konkan otla)" {\n param wide = 90\n param deep = 55\n param rise = 12 // platform height above grade\n slab name "Otla" at (0, 0) size (wide, deep) thickness rise\n}\n\n// A compact enclosed wet area (bathroom / WC): a small fully-walled room with a\n// door on the front (south). Size it to the fixture you need.\ncomponent Bathroom goal "a compact enclosed wet area (bathroom / WC)" {\n param wide = 70\n param deep = 60\n room Bath at (0, 0) size (wide, deep) {\n wall north east west\n wall south { door BathDoor at 20 size (30, 78) }\n }\n}\n\n// A cooking area with an L-shaped masonry counter in the corner. Fixed size (the\n// counter path can\'t be parametric), so the room exactly fits its counter.\ncomponent Kitchen goal "a cooking area with an L-shaped counter platform" {\n room Kitchen at (0, 0) size (150, 120) {\n wall north east south west\n }\n kitchen name "Counter" path ((8, 8), (130, 8), (130, 100)) side right depth 22 height 36\n}\n\n// A tulsi vrindavan \u2014 the raised masonry planter for the sacred basil that stands\n// in a Konkan courtyard. A small square raised block; place it in the aangan.\ncomponent TulsiVrindavan goal "a raised courtyard planter for tulsi (sacred basil)" {\n param wide = 24 // square side\n param rise = 30 // planter height\n slab name "Tulsi" at (0, 0) size (wide, wide) thickness rise\n}\n\n// A parapet \u2014 a low wall enclosing a terrace edge (open at the top, no roof).\n// Stamp it around a flat roof / terrace slab. (Per-side wall height is a fixed\n// literal here \u2014 parametric per-side wall heights aren\'t supported yet.)\ncomponent Parapet goal "a low wall enclosing a terrace edge" {\n param wide = 200\n param deep = 200\n room Terrace at (0, 0) size (wide, deep) {\n wall north east south west height 36\n }\n}\n'
419032
+ "source": '// konkan/base.wdl \u2014 a starter pack of reusable, goal-tagged Konkan house parts.\n//\n// A MODULE (no `house` body): import it and stamp its components onto a floor \u2014\n// import "konkan/base" as kb\n// floor 1 "Ground" { use kb.Stairwell at (208, 64) with { rise = 116 } }\n//\n// Each component is authored in LOCAL coordinates (origin 0,0) and is flat\n// (it does not `use` other components), so it stamps cleanly into any host.\n// The `goal` line is the discovery key \u2014 `wadi_module "konkan/base"` (or a\n// `wadi_modules` query) surfaces the component whose goal matches the intent.\n\n// Climb one floor. A single straight run for a short rise; give `run` and the\n// staircase auto-folds into switchback flights (max_run) when the rise is tall.\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116 // total height to the floor above (= floor_height)\n param run = 200 // max horizontal run before a switchback landing\n staircase name "Stair" at (0, 0) step (7, 11, 44) direction south total_height rise max_run run\n}\n\n// A shaded sit-out running along the front of the house \u2014 the room is open to\n// the south (front) and enclosed on the other three sides. Add a roof + pillars\n// in the host if you want it covered.\ncomponent Verandah goal "a shaded sit-out along the house front" {\n param across = 200 // span across the front\n param deep = 70 // how far it projects\n room Verandah at (0, 0) size (across, deep) {\n wall north east west // open to the south\n }\n}\n\n// An otla \u2014 the traditional Konkan raised platform at the entrance where people\n// sit. A low slab you place at the doorway (its thickness is the platform rise).\ncomponent Otla goal "a raised entrance platform to sit on (Konkan otla)" {\n param wide = 90\n param deep = 55\n param rise = 12 // platform height above grade\n slab name "Otla" at (0, 0) size (wide, deep) thickness rise\n}\n\n// A compact enclosed wet area (bathroom / WC): a small fully-walled room with a\n// door on the front (south). Size it to the fixture you need.\ncomponent Bathroom goal "a compact enclosed wet area (bathroom / WC)" {\n param wide = 70\n param deep = 60\n room Bath at (0, 0) size (wide, deep) {\n wall north east west\n wall south { door BathDoor at 20 size (30, 78) }\n }\n}\n\n// A cooking area with an L-shaped masonry counter in the corner. Fixed size (the\n// counter path can\'t be parametric), so the room exactly fits its counter.\ncomponent Kitchen goal "a cooking area with an L-shaped counter platform" {\n room Kitchen at (0, 0) size (150, 120) {\n wall north east south west\n }\n kitchen name "Counter" path ((8, 8), (130, 8), (130, 100)) side right depth 22 height 36\n}\n\n// A tulsi vrindavan \u2014 the raised masonry planter for the sacred basil that stands\n// in a Konkan courtyard. A small square raised block; place it in the aangan.\ncomponent TulsiVrindavan goal "a raised courtyard planter for tulsi (sacred basil)" {\n param wide = 24 // square side\n param rise = 30 // planter height\n slab name "Tulsi" at (0, 0) size (wide, wide) thickness rise\n}\n\n// A parapet \u2014 a low wall enclosing a terrace edge (open at the top, no roof).\n// Stamp it around a flat roof / terrace slab. (Per-side wall height is a fixed\n// literal here \u2014 parametric per-side wall heights aren\'t supported yet.)\ncomponent Parapet goal "a low wall enclosing a terrace edge" {\n param wide = 200\n param deep = 200\n room Terrace at (0, 0) size (wide, deep) {\n wall north east south west height 36\n }\n}\n'
418051
419033
  }
418052
419034
  };
418053
419035