-
Notifications
You must be signed in to change notification settings - Fork 27
Description
My brain is running round in circles trying to design this in a vacuum, so I thought I'd sketch out some high level thoughts on this stuff. There are a bunch of interlocking concerns, which makes it a little hard to figure out how to make any headway on it.
Currently our loader/driver API lives in the pikelet-driver, but it leaves a lot to be desired. Ultimately we want a Rust API that maintains some incrementally accumulated state, and has an API with functions that give a nice way to:
- parse source code
- type check ASTs
- evaluate expressions
- compile stuff
- load primitive functions
- query the current state
- type at cursor position
- jump to definition
- complete at cursor
- find all references
- find all implementations
- editor actions
- rename symbol
- autoformat
- case split
- move hole into binding
- search for hole substitutions
- inline definition
- extract definition
The Pikelet loader API would probably be consumed by the following clients:
- Pikelet CLI tools:
- the compiler
- the REPL
- the language server
- the package manager
- an application that embeds Pikelet as a scripting language
- a rust application, eg. a game
- via web assembly, eg. sordina/pigraph
- via a C ffi
- exotic editor/code visualisation tools
- structured editing, for example:
- bidirectional editors
Import paths may be:
- relative to the current file
- global
- from a built-in, eg. primitive functions
- from a package dependency, or the standard library
- from a dynamically loaded/compiled script
Paths need to be followed in topological order, forming a DAG. We will want to be able to listen to the file system for updates, and incrementally update as needed.
We probably want to avoid baking in a heavy compiler back-end (like LLVM) at this level, although I also wouldn't rule out including a JIT (like CraneLift) for evaluating expressions at compile time.