mthom / scryer-prolog

A modern Prolog implementation written mostly in Rust.
BSD 3-Clause "New" or "Revised" License
2.02k stars 117 forks source link

WIT definitions for Wasm Component Model #2012

Open guregu opened 1 year ago

guregu commented 1 year ago

WIT is an IDL for describing Wasm components, which wit-bindgen can use to generate code for various languages to interface with. wit-bindgen takes care of all the tedious data munging bits and would make it easy to e.g. embed Scryer as a library in various other programming languages.

Let's create a basic WIT definition for Prolog and explore what the API might look like. From there, we could create libraries for JS and other languages that take advantage of it. This would let us unite our efforts towards making user friendly libraries that could support various Prologs under a unified API.

aarroyoc commented 1 year ago

I think ideally the Wasm interface should be equal (or very similar) to the interface for non-Wasm bindings (via library, as is happening in https://github.com/mthom/scryer-prolog/pull/1880)

guregu commented 1 year ago

@aarroyoc this part, right? https://github.com/mthom/scryer-prolog/pull/1880/files#diff-52044e834bac7030da1f0c418d81dc4773d33df32ab26dd0b6f6913175900c2eR51-R147

Agreed. I think that's a solid minimal API (or at least a good starting point to test it out).

guregu commented 1 year ago

Value enums from that PR should be perfect for WIT as well.

guregu commented 3 months ago

Small update on this: I've finally got around to experimenting a bit with a WIT API definition, and it ended up very similar to this bit here: https://github.com/mthom/scryer-prolog/blob/d6ac03552d8484f8ad7c4307d1c9cfb5db46b16f/src/machine/parsed_results.rs#L107 However, WIT doesn't support recursive types 😢

For example, a Term type might look like this:

    variant term {
        number(number),
        atom(string),
        compound(compound),
        chars(string),
        variable(string),
        pl-list(list<term>), // "list" is a reserved word
    }

but error out because the list variant refers to the type term itself (and so does a compound's arguments). Some discussion here: https://github.com/WebAssembly/component-model/issues/56#issuecomment-1557353084

Seems like the workaround is to return a top-level list of objects and then refer to that using integer indices. That would make the API response for a query look something like this (JSON-ish pseudocode):

{
    "goal": "X = foo(bar, baz)",
    "terms": [compound("foo", [ref(1), ref(2)]), atom("bar"), atom("baz")],
    "solution": {"X": ref(0)}
}

I'll continue playing around with it, and if anyone has a good idea for a workaround let me know!

mthom commented 3 months ago

Not sure if it helps with the lack of recursive type support in wit-bindgen but I am in the process of removing Term entirely from Scryer.