2.8 KiB
2.8 KiB
Runtime Model
処理系の評価結果は、具体値と抽象値を区別した runtime value として扱う。
value、constraints、default を横並びに持つ構造にはしない。
RuntimeValue
RuntimeValue =
Concrete(ConcreteValue)
Abstract(AbstractValue)
Concrete は明示的な値である。
Abstract は、まだ具体値に確定していない制約付きの値である。
ConcreteValue
ConcreteValue =
String(String)
Int(i64)
Float(f64)
Bool(bool)
Array(Vec<ThunkId>)
Object(ObjectValue)
Function(FunctionValue)
object は concrete structure として扱う。 ただし、各 field の中身は concrete value でも abstract value でもよい。
ObjectValue:
fields: Map<Symbol, ThunkId>
例えば以下の schema object は、object 自体は concrete だが、field の値は abstract value になる。
MyConfig = {
host = String;
port = Int default 8080;
};
概念的には以下である。
Concrete(Object {
host -> Thunk(Abstract { constraints: [String], default: none })
port -> Thunk(Abstract { constraints: [Int], default: 8080 })
})
AbstractValue
AbstractValue {
constraints: Vec<Constraint>
default: Option<ThunkId>
}
default は AbstractValue にだけ存在する。
明示的な concrete value がある場合、default は保持しない。
port = Int default 8080;
これは以下の runtime value になる。
Abstract {
constraints: [Type(Int)]
default: Some(Thunk(8080))
}
port = 8000;
これは以下である。
Concrete(Int(8000))
Constraint
constraint は concrete value とは別の型として扱う。
Constraint =
Type(PrimitiveType)
Compare(Op, Literal)
Regex(Pattern)
BuiltinPredicate(Symbol)
ObjectConstraint(...)
初期実装では、object の形は主に Concrete(Object) の field に Abstract を置くことで表現する。
object 全体にかかる constraint は必要になった時点で追加する。
Data
materialize 後の出力可能な値は runtime value とは別型にする。
Data =
String(String)
Int(i64)
Float(f64)
Bool(bool)
Array(Vec<Data>)
Object(Map<Symbol, Data>)
Function、未解決の Abstract、未評価の thunk は Data にはならない。
命名
実装内部では RuntimeValue を短く Value と呼んでもよい。
ただし、materialize 後の出力値とは区別する。
推奨する区別:
RuntimeValue / Value 言語内部の評価結果。Abstract を含む。
ConcreteValue 明示的な具体値。
AbstractValue constraint と default を持つ抽象値。
Data 外部へ出力可能な最終データ。