Sign in

    pkl

    Pure MoonBit parser, interpreter, and typechecker experiments for Apple's Pkl language.

    moonbit
    pkl
    parser
    interpreter
    typechecker
    Download zip
    Author
    Version
    0.4.0
    License
    Apache-2.0
    Last updated
    2 months ago
    Downloads
    832

    #mizchi/pkl

    Pure-MoonBit parser, typechecker, evaluator, and renderer for Apple's Pkl language. Builds clean on all four MoonBit targets (native, js, wasm, wasm-gc); the @pkl surface is pure (no IO, no async) so an embedder running in a wasm sandbox can depend on it directly. The cmd/mpkl package includes a Marketplace SKILL.md and a moon runwasm entry for parse, check, eval, and format workflows over inline source or local files with relative imports and cache-backed package:// modules.

    The CLI lives in cmd/mpkl (mpkl parse|check|eval|test|format|analyze|codegen). See the repository README for install / usage / benchmarks against Apple Pkl.

    #What the library exposes

    Entry points:

    • parse_source(source) -> ParseResult — top-level CST-backed parse.
    • eval_source(source) -> EvalResult — parse + evaluate a single source.
    • typecheck_source(source) -> TypecheckResult — parse + typecheck.
    • lint_program(program) -> Array[LintFinding] — static-analysis pass.
    • codegen(program, target) -> String — code generator dispatch (CodegenTarget::MoonBit today).
    • AnalysisSession — incremental, ripple-backed analysis for editor / multi-file flows.

    Renderers (one entry per format): render_value (PCF, default), plus render_value_as_json / _yaml / _xml / _textproto / _properties / _plist / _jsonnet and their _document / _fragment / _with_indent / _with_options variants. Apple Pkl's output { renderer = new <Renderer> { ... } } is honoured.

    Sandbox configuration (configure_sandbox_* / register_*): module allowlist, module paths, package caches, prop: / env: populating, static read-resource registration, import-glob registration, extends-chain parent binding resolver, and the lazy stdlib base.pkl loader. The dynamic resource-reader hook configure_sandbox_resource_reader(scheme, fn(uri) -> SandboxResource?) lets an embedded caller service read("scheme:path") calls in-process (HTTP / DB / shell-exec etc.).

    #Status

    The release gate passes Apple Pkl's upstream LanguageSnippetTests across the advertised renderers (PCF, JSON, YAML, properties, plist, textproto, XML, Jsonnet). Coverage of the Apple Pkl test surface is 98.5% by gold-match; see the repository's TODO.md for the remaining fixture inventory.

    Known gaps for embedded callers:

    • Eager property evaluation. mpkl evaluates every property of a new T { ... } object eagerly; Apple Pkl is lazy. Object bodies that contain a slot whose body errors on a code path the caller never reads (new Result { cases = cases.length; ... } where cases.length would fail but the caller only reads result.passed) still error in mpkl. Tracked as a follow-up.
    • External-reader subprocess protocol. Apple Pkl's --external-resource-reader=<scheme>=<bin> ships a MessagePack-framed IPC; mpkl's in-process callback hook is the embedded substitute. A subprocess-side adapter would need MoonBit's core / x packages to ship a subprocess runtime first.

    #Versioning

    This is 0.4.0. Pre-1.0 minor bumps may break the public surface — semver promises kick in at 1.0.0.

    AnalysisSession

    pub struct AnalysisSession {
    // private fields
    }

    AnalysisSession::eval_path

    fn AnalysisSession::eval_path(self : AnalysisSession, path : String) -> EvalResult

    AnalysisSession::new

    AnalysisSession::reset_stats

    fn AnalysisSession::reset_stats(self : AnalysisSession) -> Unit

    AnalysisSession::set_source

    fn AnalysisSession::set_source(self : AnalysisSession, path : String, source : String) -> Unit

    AnalysisSession::stats

    AnalysisSession::typecheck_path

    fn AnalysisSession::typecheck_path(self : AnalysisSession, path : String) -> TypecheckResult

    AnalysisStats

    pub(all) struct AnalysisStats {
    parse_count : Int
    typecheck_count : Int
    eval_count : Int
    } derive(Eq,
    Debug
    )

    Annotation

    pub(all) struct Annotation {
    class_name : String
    body_kind : AnnotationBodyKind
    body_text : String
    } derive(Eq,
    Debug
    )

    PKL-128d: structured capture of a single annotation that precedes a declaration. class_name holds the identifier after @ (e.g. "Deprecated", "ModuleInfo", "my.pkg.Custom"). body_text is the verbatim source between the surrounding delimiters; the body_kind field identifies which delimiters were used so a downstream tool (pkldoc / codegen) can re-parse the body in the matching mode without scanning back to the open token.

    Forms recognised:
    • @Name → body_kind = NoBody, body_text = ""
    • @Name(arg, ...) → body_kind = ParenBody, body_text = inside parens
    • @Name { field = expr } → body_kind = BraceBody, body_text = inside braces

    Capturing only the raw text keeps the slice tight: the downstream consumer can lex/parse the body when needed, and the AST avoids carrying a second Expr-tree shape for arguments that the evaluator never sees.

    AnnotationBodyKind

    pub(all) enum AnnotationBodyKind {
    NoBody
    ParenBody
    BraceBody
    } derive(Eq,
    Debug
    )

    BinaryOp

    pub(all) enum BinaryOp {
    Add
    Subtract
    Multiply
    Divide
    IntDivide
    Modulo
    Power
    Equal
    NotEqual
    LessThan
    LessOrEqual
    GreaterThan
    GreaterOrEqual
    And
    Or
    NullCoalesce
    Is
    As
    Pipe
    } derive(Eq,
    Debug
    )

    Binding

    pub(all) struct Binding {
    name : String
    type_name : String?
    value : Expr
    exported : Bool
    is_const : Bool
    annotations : Array[Annotation]
    abstract_slot : Bool
    sibling_slot : Bool
    } derive(Eq,
    Debug
    )

    ClassDecl

    pub(all) struct ClassDecl {
    name : String
    type_parameters : Array[String]
    type_parameter_bounds : Array[String?]
    parent_name : String?
    properties : Array[ClassProperty]
    methods : Array[FunctionDecl]
    annotations : Array[Annotation]
    is_abstract : Bool
    } derive(Eq,
    Debug
    )

    ClassExport

    pub(all) struct ClassExport {
    name : String
    parent_name : String?
    properties : Array[ClassProperty]
    methods : Array[FunctionDecl]
    } derive(Eq,
    Debug
    )

    ClassProperty

    pub(all) struct ClassProperty {
    name : String
    type_name : String?
    value : Expr?
    annotations : Array[Annotation]
    } derive(Eq,
    Debug
    )

    CodegenTarget

    pub(all) enum CodegenTarget {
    MoonBit
    } derive(Eq,
    Debug
    )

    PKL-131b: target-driven codegen dispatcher. Only MoonBit is wired today; the enum + dispatcher pair keeps the public surface stable when future targets (Java / Kotlin / Swift / Go / TypeScript) land — embedders never need to swap entry points or learn a new per-target function name.

    Declaration

    pub(all) enum Declaration {
    ClassDeclaration(ClassDecl)
    FunctionDeclaration(FunctionDecl)
    TypeAliasDeclaration(TypeAliasDecl)
    } derive(Eq,
    Debug
    )

    Diagnostic

    pub(all) struct Diagnostic {
    message : String
    start : Int
    end : Int
    } derive(Eq,
    Debug
    )

    EvalResult

    pub(all) enum EvalResult {
    EvalOk(Value)
    EvalError(Array[Diagnostic])
    } derive(Eq,
    Debug
    )

    Expr

    pub(all) enum Expr {
    IntLiteral(Int64)
    FloatLiteral(Double)
    BoolLiteral(Bool)
    StringLiteral(String)
    NullLiteral
    Identifier(String)
    ImportExpr(String)
    ImportGlobExpr(String)
    ObjectLiteral(Array[ObjectMember])
    TypedObjectLiteral(String, Array[ObjectMember])
    ListingLiteral(Array[Expr])
    MappingLiteral(Array[MappingEntry])
    MemberAccess(Expr, String)
    SafeMemberAccess(Expr, String)
    SubscriptAccess(Expr, Expr)
    AmendExpr(Expr, Array[ObjectMember])
    CallExpr(Expr, Array[Expr])
    LambdaExpr(Array[FunctionParameter], Expr, String?)
    LetExpr(String, String?, Expr, Expr)
    NonNullExpr(Expr)
    UnaryExpr(UnaryOp, Expr)
    BinaryExpr(BinaryOp, Expr, Expr)
    ConditionalExpr(Expr, Expr, Expr)
    ForGenerator(String, String?, Expr, Array[ObjectMember], String?, String?)
    WhenSpread(Expr)
    InterpolatedString(Array[Expr])
    NullSafeCallExpr(Expr, Array[Expr])
    UnsupportedExpr
    ErrorExpr(String)
    } derive(Eq,
    Debug
    )

    FunctionDecl

    pub(all) struct FunctionDecl {
    name : String
    type_parameters : Array[String]
    type_parameter_bounds : Array[String?]
    parameters : Array[FunctionParameter]
    return_type_name : String?
    body : Expr?
    annotations : Array[Annotation]
    is_const : Bool
    is_abstract : Bool
    } derive(Eq,
    Debug
    )

    FunctionParameter

    pub(all) struct FunctionParameter {
    name : String
    type_name : String?
    } derive(Eq,
    Debug
    )

    ImportDecl

    pub(all) struct ImportDecl {
    uri : String
    import_name : String
    is_glob : Bool
    } derive(Eq,
    Debug
    )

    LintFinding

    pub(all) struct LintFinding {
    rule : String
    message : String
    } derive(Eq,
    Debug
    )

    PKL-102: lightweight static-analysis checks surfaced through pkl analyze <file>. Each finding identifies a category (rule) and carries a human-readable message. Source positions become useful once PKL-107 propagates byte offsets into the AST; until then the CLI prints path: rule: message and the byte offsets stay at -1.

    MappingEntry

    pub(all) struct MappingEntry {
    key : Expr
    value : Expr
    } derive(Eq,
    Debug
    )

    ModuleRelation

    pub(all) struct ModuleRelation {
    kind : ModuleRelationKind
    uri : String
    } derive(Eq,
    Debug
    )

    ModuleRelationKind

    pub(all) enum ModuleRelationKind {
    ModuleAmends
    ModuleExtends
    } derive(Eq,
    Debug
    )

    ObjectMember

    pub(all) struct ObjectMember {
    name : String
    type_name : String?
    value : Expr
    annotations : Array[Annotation]
    } derive(Eq,
    Debug
    )

    ParseResult

    pub(all) struct ParseResult {
    root :
    SyntaxNode

    program : Program
    diagnostics : Array[Diagnostic]
    unsupported_syntax : Array[UnsupportedSyntax]
    } derive(Eq)

    Program

    pub(all) struct Program {
    module_name : String?
    module_relation : ModuleRelation?
    imports : Array[ImportDecl]
    declarations : Array[Declaration]
    bindings : Array[Binding]
    body : Expr?
    module_annotations : Array[Annotation]
    } derive(Eq,
    Debug
    )

    SandboxResource

    pub(all) struct SandboxResource {
    uri : String
    resource_uri : String
    text : String
    } derive(Eq,
    Debug
    )

    Type

    pub(all) enum Type {
    IntType
    FloatType
    BoolType
    StringType
    NullType
    ObjectType(Array[TypeMember])
    ClassType(String, Array[TypeMember])
    ListingType(Array[Type])
    MappingType(Array[TypeEntry])
    PairType(Type, Type)
    IntSeqType
    SetType(Array[Type])
    MapType(Array[TypeEntry])
    FunctionType(Array[Type], Type)
    ConstrainedType(String, Type)
    UnionType(Array[Type])
    NullableType(Type)
    DefaultedType(Type)
    TypeVariable(String)
    AnyType
    UnknownType
    } derive(Eq,
    Debug
    )

    TypeAliasDecl

    pub(all) struct TypeAliasDecl {
    name : String
    type_parameters : Array[String]
    target : String
    annotations : Array[Annotation]
    } derive(Eq,
    Debug
    )

    TypeEntry

    pub(all) struct TypeEntry {
    key : Type
    value : Type
    } derive(Eq,
    Debug
    )

    TypeExport

    pub(all) struct TypeExport {
    name : String
    typ : Type
    } derive(Eq,
    Debug
    )

    TypeMember

    pub(all) struct TypeMember {
    name : String
    typ : Type
    } derive(Eq,
    Debug
    )

    TypecheckResult

    pub(all) enum TypecheckResult {
    TypeOk(Type)
    TypeError(Array[Diagnostic])
    } derive(Eq,
    Debug
    )

    UnaryOp

    pub(all) enum UnaryOp {
    Negate
    Not
    } derive(Eq,
    Debug
    )

    UnsupportedSyntax

    pub(all) struct UnsupportedSyntax {
    start : Int
    end : Int
    text : String
    kind : String
    } derive(Eq,
    Debug
    )

    Value

    pub(all) enum Value {
    IntValue(Int64)
    FloatValue(Double)
    BoolValue(Bool)
    StringValue(String)
    NullValue
    DeferredImportValue(String)
    ObjectValue(Array[ValueMember])
    ListingValue(Array[Value])
    ListValue(Array[Value])
    MappingValue(Array[ValueEntry])
    DefaultedListingValue(Array[Value], Array[Value], Value)
    DefaultedMappingValue(Array[ValueEntry], Array[ValueEntry], Value)
    PairValue(Value, Value)
    IntSeqValue(Int64, Int64, Int64)
    SetValue(Array[Value])
    MapValue(Array[ValueEntry])
    FunctionValue(Array[FunctionParameter], Expr, String?, Array[ValueBinding], Int)
    DurationValue(Double, String)
    DataSizeValue(Double, String)
    RegexValue(String)
    BytesValue(Bytes)
    } derive(Eq,
    Debug
    )

    ValueBinding

    pub(all) struct ValueBinding {
    name : String
    value : Value
    } derive(Eq,
    Debug
    )

    ValueEntry

    pub(all) struct ValueEntry {
    key : Value
    value : Value
    } derive(Eq,
    Debug
    )

    ValueMember

    pub(all) struct ValueMember {
    name : String
    value : Value
    annotations : Array[Annotation]
    source : Expr?
    } derive(
    Debug
    )

    clear_sandbox_env_vars

    fn clear_sandbox_env_vars() -> Unit

    clear_sandbox_resource_readers

    fn clear_sandbox_resource_readers() -> Unit

    Drop all dynamic resource readers. Useful for embedded callers that share a sandbox across runs.

    codegen

    fn codegen(program : Program, target : CodegenTarget) -> String

    PKL-131b: single entry point for codegen, parametric over the target language. Returns the generated source as a String; embedders write it to disk / a stream as they see fit. Each target's lowering rules live in its own helper so the dispatcher stays a one-line match.

    configure_sandbox_allowed_modules

    fn configure_sandbox_allowed_modules(patterns : Array[String]) -> Unit

    Replace the configured allowed-modules pattern list. An empty list disables the allow-list (everything is permitted).

    configure_sandbox_env_vars

    fn configure_sandbox_env_vars(vars : Map[String, String]) -> Unit

    configure_sandbox_module_paths

    fn configure_sandbox_module_paths(dirs : Array[String]) -> Unit

    Replace the configured module-path search list. Directories are consulted in order when resolving an unqualified import.

    configure_sandbox_package_caches

    fn configure_sandbox_package_caches(dirs : Array[String]) -> Unit

    Replace the configured package-cache search list. See SandboxConfig.package_caches for the layout each directory must follow.

    configure_sandbox_props

    fn configure_sandbox_props(props : Map[String, String]) -> Unit

    Replace the configured props map. Pass an empty map to clear.

    configure_sandbox_resource_reader

    fn configure_sandbox_resource_reader(scheme : String, reader : (String) -> SandboxResource?) -> Unit

    Register a dynamic resource reader for scheme: URIs. The reader is invoked the first time read("<scheme>:<path>") misses the static read_resources map. Returning None falls back to the "Cannot find / refusing" diagnostic. Re-registering for the same scheme replaces the prior reader. Pass the bare scheme (no trailing colon) — configure_sandbox_resource_reader("cmd", fn) services read("cmd:ls") etc.

    configure_stdlib_base_paths

    fn configure_stdlib_base_paths(loader : () -> String?) -> Unit

    Register candidate filesystem paths for base.pkl. The first readable path is loaded lazily on the first sandbox_stdlib_base_source() call. Reads go through stdlib_base_loader so this module avoids a direct dependency on @fs.

    configure_stdlib_base_source

    fn configure_stdlib_base_source(source : String) -> Unit

    Eagerly register the base.pkl source text. Use this when the caller already holds the source in memory (tests, embedded callers). CLI callers should prefer configure_stdlib_base_paths so the file is only read on first reflect use.

    eval_source

    fn eval_source(source : String) -> EvalResult

    extract_output_value

    fn extract_output_value(value : Value) -> Value

    Resolve a top-level module value to what Apple Pkl actually renders.

    output is a hidden module property, so it never appears in rendered output. When the user sets output.value = <expr> (as pkspec's Test.pkl does via output { value = new Rendered { ... } }), that value — not the raw module body — is the render target. A bare output member (only renderer / other knobs, no value) is simply dropped.

    eval_source deliberately keeps the output member on the raw eval result (see PKL-104); render-boundary callers (the CLI / loader) apply this before handing a value to render_value_as_json & friends. Returns the value unchanged when it isn't a module-shaped ObjectValue carrying an output member.

    fdlibm_cos

    fn fdlibm_cos(x : Double) -> Double

    fdlibm_sin

    fn fdlibm_sin(x : Double) -> Double

    fdlibm_tan

    fn fdlibm_tan(x : Double) -> Double

    lint_program

    fn lint_program(program : Program) -> Array[LintFinding]

    Entry point: walk program once per rule and accumulate findings in source order so the CLI output is stable across runs.

    lookup_triple_dot_resolution

    fn lookup_triple_dot_resolution(from : String, uri : String) -> String?

    PKL-148r: look up a previously-registered triple-dot resolution. Returns the absolute path the CLI loaded the module under, or None if the CLI never saw this (from, uri) pair.

    parse_source

    fn parse_source(source : String) -> ParseResult

    register_import_glob

    fn register_import_glob(from : String, pattern : String, uris : Array[String]) -> Unit

    register_import_glob_errors

    fn register_import_glob_errors(from : String, pattern : String, errors : Map[String, String]) -> Unit

    register_module_alias

    fn register_module_alias(raw : String, resolved : String) -> Unit

    PKL-148bo: register a canonical alias from one URI form to another. Used for import "@dep/foo.pkl" → package://...#/foo.pkl so the resolvedImports table sees the right shape even when callers ask for the raw form.

    register_module_imports

    fn register_module_imports(module_uri : String, import_uris : Array[String]) -> Unit

    PKL-148bo: record the resolved import edges for a single module. module_uri is the canonical file:///$snippetsDir/... or package://... URI of the module; import_uris is the (ordered) list of resolved URIs the module declares via import / import* / amends / extends. The list preserves source order because pkl:analyze.importGraph is order-sensitive in its rendering.

    register_read_glob

    fn register_read_glob(from : String, pattern : String, resources : Array[SandboxResource]) -> Unit

    register_read_resource

    fn register_read_resource(from : String, uri : String, visible_uri : String, resource_uri : String, text : String) -> Unit

    register_triple_dot_resolution

    fn register_triple_dot_resolution(from : String, uri : String, resolved : String) -> Unit

    PKL-148r: register a triple-dot import resolution. Called by the CLI loader after @fs.path_exists finds the matching ancestor candidate, so the analysis-layer resolver can map the same (from, uri) pair back to the same absolute path without re-doing FS access.

    render_type

    fn render_type(typ : Type) -> String

    render_value

    fn render_value(value : Value) -> String

    render_value_as_json

    fn render_value_as_json(value : Value) -> String

    render_value_as_json_document

    fn render_value_as_json_document(value : Value) -> String

    render_value_as_json_document_with_indent

    fn render_value_as_json_document_with_indent(value : Value, indent_text : String) -> String

    render_value_as_json_with_indent

    fn render_value_as_json_with_indent(value : Value, indent_text : String) -> String

    render_value_as_jsonnet

    fn render_value_as_jsonnet(value : Value) -> String

    render_value_as_jsonnet_document

    fn render_value_as_jsonnet_document(value : Value) -> String

    render_value_as_jsonnet_document_with_indent

    fn render_value_as_jsonnet_document_with_indent(value : Value, indent_text : String) -> String

    render_value_as_jsonnet_document_with_options

    fn render_value_as_jsonnet_document_with_options(value : Value, indent_text : String, omit_null_properties : Bool) -> String

    render_value_as_jsonnet_with_indent

    fn render_value_as_jsonnet_with_indent(value : Value, indent_text : String) -> String

    render_value_as_jsonnet_with_options

    fn render_value_as_jsonnet_with_options(value : Value, indent_text : String, omit_null_properties : Bool) -> String

    render_value_as_pcf_document

    fn render_value_as_pcf_document(value : Value) -> String

    render_value_as_pcf_document_with_indent

    fn render_value_as_pcf_document_with_indent(value : Value, indent_text : String) -> String

    render_value_as_pcf_document_with_options

    fn render_value_as_pcf_document_with_options(value : Value, indent_text : String, use_custom_string_delimiters : Bool) -> String

    render_value_as_pcf_fragment

    fn render_value_as_pcf_fragment(value : Value) -> String

    render_value_as_pcf_fragment_with_indent

    fn render_value_as_pcf_fragment_with_indent(value : Value, indent_text : String) -> String

    render_value_as_pcf_fragment_with_options

    fn render_value_as_pcf_fragment_with_options(value : Value, indent_text : String, use_custom_string_delimiters : Bool) -> String

    render_value_as_plist

    fn render_value_as_plist(value : Value) -> String

    render_value_as_plist_fragment

    fn render_value_as_plist_fragment(value : Value) -> String

    render_value_as_properties

    fn render_value_as_properties(value : Value) -> String

    render_value_as_properties_fragment

    fn render_value_as_properties_fragment(value : Value) -> String

    render_value_as_protobuf_fragment

    fn render_value_as_protobuf_fragment(value : Value, indent_text : String) -> String

    render_value_as_textproto

    fn render_value_as_textproto(value : Value) -> String

    render_value_as_textproto_fragment

    fn render_value_as_textproto_fragment(value : Value, indent_text : String) -> String

    render_value_as_textproto_with_indent

    fn render_value_as_textproto_with_indent(value : Value, indent_text : String) -> String

    render_value_as_xml

    fn render_value_as_xml(value : Value) -> String

    render_value_as_xml_fragment

    fn render_value_as_xml_fragment(value : Value, indent_text : String) -> String

    render_value_as_xml_with_options

    fn render_value_as_xml_with_options(value : Value, root_element_name : String, indent_text : String, xml_version : String) -> String

    render_value_as_yaml

    fn render_value_as_yaml(value : Value) -> String

    render_value_as_yaml_fragment

    fn render_value_as_yaml_fragment(value : Value) -> String

    render_value_as_yaml_fragment_with_mode

    fn render_value_as_yaml_fragment_with_mode(value : Value, indent_width : Int, is_stream : Bool, mode : String) -> String

    render_value_as_yaml_fragment_with_options

    fn render_value_as_yaml_fragment_with_options(value : Value, indent_width : Int, is_stream : Bool) -> String

    render_value_as_yaml_stream

    fn render_value_as_yaml_stream(value : Value, indent_width : Int) -> String

    render_value_as_yaml_with_indent_width

    fn render_value_as_yaml_with_indent_width(value : Value, indent_width : Int) -> String

    render_value_as_yaml_with_mode

    fn render_value_as_yaml_with_mode(value : Value, indent_width : Int, is_stream : Bool, mode : String) -> String

    Mode-aware entry point used by the runtime renderer dispatch. External callers should prefer this when the YamlRenderer's mode slot matters; render_value_as_yaml_with_options keeps the historical default-"compat" behaviour intact.

    render_value_as_yaml_with_options

    fn render_value_as_yaml_with_options(value : Value, indent_width : Int, is_stream : Bool) -> String

    render_value_with_pcf_indent

    fn render_value_with_pcf_indent(value : Value, indent_text : String) -> String

    render_value_with_pcf_options

    fn render_value_with_pcf_options(value : Value, indent_text : String, use_custom_string_delimiters : Bool) -> String

    reset_sandbox_io_cache

    fn reset_sandbox_io_cache() -> Unit

    sandbox_all_module_uris

    fn sandbox_all_module_uris() -> Array[String]

    PKL-148bo: every module URI we've registered. The intrinsic uses this to break out of cycles cleanly.

    sandbox_is_module_allowed

    fn sandbox_is_module_allowed(uri : String) -> Bool

    True when uri is permitted by the current allow-list. An empty allow-list means "no restriction" so the default CLI behaviour is unchanged from before the slice. Each pattern is treated as a literal URI prefix — the format matches Apple Pkl's |-separated prefix lookup (e.g. pkl:|file:|https:).

    Bare filesystem paths (no scheme: prefix) bypass the allow-list because the check is intended for sandbox-relevant URIs that cross trust boundaries (https:, package:, the stdlib pkl:, etc.). The entrypoint and locally-rooted imports are already gated by filesystem permissions and the user typing the path on the command line, so re-checking them against the same allow-list would force users to spell out every directory.

    sandbox_module_alias

    fn sandbox_module_alias(raw : String) -> String?

    sandbox_module_imports

    fn sandbox_module_imports(module_uri : String) -> Array[String]?

    PKL-148bo: lookup helper used by the _pkl_analyze_import_graph intrinsic to walk a recorded module's adjacency list.

    sandbox_module_paths

    fn sandbox_module_paths() -> Array[String]

    Iterate the configured --module-path directories in CLI order. The loader prepends each directory to an unqualified import URI and tries the resulting path; the first hit wins. Returning the array directly keeps the loader free of an iterator wrapper.

    sandbox_package_caches

    fn sandbox_package_caches() -> Array[String]

    Iterate the configured --package-cache directories in CLI order.

    sandbox_stdlib_base_source

    fn sandbox_stdlib_base_source() -> String?

    typecheck_source

    fn typecheck_source(source : String) -> TypecheckResult