メインコンテンツまでスキップ

import — 層を読む

import は一棟を複数のファイルに分けて書くための一語である。一行が一つの層を読み、読まれた層は一棟のモデルへ合成される。

import <相対パス>

パスはそれを書いたファイルからの相対であり、実行時のカレントディレクトリからではない。拡張子まで書く。

import ./assets.muro
import ./site.muro
import ./L1.muro
import ./L2.muro

一つのファイルが一つの層である

koyu には「層の宣言」という文が無い。ファイルがそのまま層である。import はファイルを読む文であり、同時に層を一つ積む文でもある。

読み込みの起点になるファイルを entry と呼ぶ。koyu checkkoyu plan に渡すのは常に entry であり、import は自動でたどられる。

examples/house/ は一棟を 5 ファイルに割っている。

ファイル持つもの
main.muroentry — 版・建物名・単位・グリッド・レベル、import の並び、階を跨ぐ関係
assets.muro建具アセット — 建具表にあたる層
site.muro敷地と外部空間、塀・門扉
L1.muro1階の空間と境界
L2.muro2階の空間と境界
$ koyu check examples/house/main.muro
✔ Consistent — 13 spaces / 31 boundaries
  Structural consistency only — architectural validity is what koyu validate says, separately

層の並びは深さ優先で平らにした列である

import は入れ子にできる — 読まれた層がさらに import を書いてよい。その木を深さ優先の先行順で平らにした列が、層の並びである。

親は子より先に列へ入る。ある import 行が読んだ層の内側の層は、その行の次の import 行より前に来る。

# main.muro
import ./a.muro     # a は自身の中で b を import している
import ./c.muro     # c も b を import している
$ koyu layers main.muro
Layers (weakest first — later layers are stronger):
  0	main.muro
  1	a.muro
  2	b.muro
  3	c.muro

添字 0 は entry である。entry はどのファイルよりも先に列へ入る。

同じ層が二度 import されても、最初の位置を保つ。上の例で b.muroa.muro からも c.muro からも読まれるが、列に一度しか現れず、その位置は最初に読まれた添字 2 である。二重 import も循環も冪等で、エラーにはならない — 層は一度だけ合成される。

この並びは飾りではない。後の層ほど強く、添字がそのまま強度である。同じ属性に二つの層が意見を持ったとき、どちらが勝つかはこの添字で決まる。強度の規則は 合成の六規則 にある。

entry が一度だけ宣言するもの

一棟の一貫性にあたる宣言は、合成のどこかで一度だけ現れなければならない。

宣言規律
koyu <版>entry でのみ、一度だけ。同じ版での再宣言もエラー
name一度だけ。同じ文字列なら再宣言してよい
unit mm何度書いてもよい (値が mm かどうかだけを見る)
grid X / grid Y軸ごとに一度だけ
level名の重複はエラー。どの層に書いてもよい
$ koyu check main.muro
✖ l.muro:line 1: The koyu version is declared only in the base layer (the entry)
$ koyu check main.muro
✖ l.muro:line 1: grid Y is declared once (in the base layer when composing)

gridlevel は entry に置かなくても通る。効いているのは場所ではなく順序で、どちらも使用より前に合成されていなければならない。慣行としては entry に置くか、entry が最初に import する基盤の層に集める。

層は単独では読めない

分担して書かれた層は gridlevel も持たないので、そのファイルだけを check に渡しても読めない。

$ koyu check examples/house/L1.muro
✖ examples/house/L1.muro:line 3: Undeclared level: level:L1

検査はつねに entry に対して行う。check plan stats json — どれも entry を渡せば合成後のモデルを見る。

前方参照

boundary は空間を前方参照してよい。階を跨ぐ関係を entry に書き、それが指す空間を後から import しても通る。

# main.muro — 空間はこの後の import で入ってくる
boundary /home/hall1 /home/hall2 type:stair

import ./L1.muro
import ./L2.muro

一方で overdrop対象が既に合成されていなければならない。上書きと削除は定義ではないので、対象の無い行はエラーになる。詳しくは over / drop を見る。

何が層に置けるか

空間・境界・ゾーン・アセット・敷地形状・柱・stack — 定義はどの層に置いてもよい。切り口は分担の単位で決める。階で割ってもよいし、建具・敷地・設備で割ってもよい。

敷地形状 (polygon) は測量由来の所与であって設計の生成物ではないので、宣言 1 行だけの層に隔離するのが標準の書き方である。examples/tower/site-geometry.muro がその形をしている。

import は残らない

正準JSON は合成後の単一のモデルであり、import の跡は残らない。5 ファイルに割って書いた建物と、同じ内容を 1 ファイルに書いた建物は、同じ正準JSONを与える。層の分け方は書き手の都合であって、建物の性質ではない。

エラー

状態出るもの
ファイルが読めないCannot read file: ./missing.muro
空間パス・ゾーンパス・アセット名の重複エラー。両者の出所を ファイル:行 で言う
grid / name / koyu の再宣言エラー
二重 import・循環エラーではない (一度だけ合成される)
$ koyu check main.muro
✖ e4.muro:line 1: Duplicate space path: /L1/a (first seen in plan.muro at line 1)

パスは同一性そのものである。別の空間なら別のパスを与える。アセット名が衝突したときは、アセットを一つの層にまとめるか、別の名を与えるか、参照する側で属性を上書きする。

これらはモデルが組み上がる前に止まる。壊れた JSON を JSON パーサが弾くのと同じ層にあり、診断として後から報告されるものではない。

API から

import はファイル合成の文である。単一の文字列を読む parse() には読み込み口が無いので、import を書いた文字列を渡すとエラーになる。

import is available only in file composition (parseFile / parseFiles / CLI)

ファイルシステムから読むなら parseFile、仮想のファイル群 (ブラウザ等) から読むなら parseFiles を使う。後者はキーが POSIX 風の相対パスで、import はそのキー空間の中で解決される。

関連

  • 合成の六規則 — 層の強度と、合成が守る六つの規則
  • over / drop — 上書きと削除、集合の編集
  • stack — 階を跨ぐ関係の一括宣言とスパン展開
  • koyu check — entry を渡す門番
  • koyu layers — 層の並びと属性の出所を印字する