74 lines
3.7 KiB
Markdown
74 lines
3.7 KiB
Markdown
|
|
# Newt
|
|
|
|
Newt is a dependently typed programming language that compiles to javascript. It is
|
|
my first attempt to write a dependent typed language. It is inspired by Idris,
|
|
Elaboration Zoo, pi-forall, and various tutorials.
|
|
|
|
I'm still learning how this stuff is done, so it's a bit of a mess. But I'm going to
|
|
work with the garage door up.
|
|
|
|
The goal is to have inductive types, pattern matching, compile to javascript, and be
|
|
self hosted. Ideally I could build a little browser "playground" to compile, view
|
|
output, and run code.
|
|
|
|
The repository is tagging `.newt` files as Agda to convince github to highlight them.
|
|
|
|
## Building
|
|
|
|
There is a `Makefile` that builds both chez and javascript versions. They end up in
|
|
`build/exec` as usual. I've also added a `pack.toml`, so `pack build` also works.
|
|
|
|
There is a vscode extension in `newt-vscode`. Running `make vscode` will build and install it. The extension expects `build/exec/newt` to exist in the workspace.
|
|
|
|
## Overview
|
|
|
|
I'm doing Type in Type for now.
|
|
|
|
The type checking and implicits are based on elaboration zoo. I'm using normalization
|
|
by evaluation with closure objects rather than HOAS. When going under binders in the
|
|
typechecking, I follow Kovács example and place a `VVar` into the environment instead of
|
|
doing `subst`.
|
|
|
|
The raw syntax is `Raw`. This is elaborated to `Tm`. There is a top level context and a
|
|
context during checking. The top level context uses names, and type checking uses deBruijn
|
|
indices for `Tm` and levels for `Val`. For compilation, this is converted to `CExp`, which works out how arity and closures will work, and then `JSExp` which is javascript AST.
|
|
|
|
I have `Let` in the core language. Partly because I'd like this to make it into javascript (only compute once), but also because it's being leveraged by the casetree stuff.
|
|
|
|
## Case Tree
|
|
|
|
I've got no idea what I'm doing here. I worked off of Jesper Cockx "Elaborating Dependent (Co)pattern Matching", leaving out codata for now.
|
|
|
|
For the dependent thing, I've change unify to return `VVar` constraints. I think such constraints would be an error while typechecking on RHS (meta solutions are handled separately). On the LHS, I'm rewriting the environment to turn the var from a bind to a define. Unification has been tweaked to look up `VVar` in environment. Bind will hand back the same `VVar`.
|
|
|
|
Some of this I could probably do with subst, but the RHS is `Raw`, it takes typechecking to turn it into a clean `Tm`, and I need this information for the typechecking. To substitute into the goal type for the RHS, I am now
|
|
doing a quote and eval to get case to expand. This is a bit of a stopgap because case is only eval'd when going
|
|
from `Tm` to `Val`. I think I'll need a way to eval a VCase during unification, as we do with function applications.
|
|
|
|
## Evaluation
|
|
|
|
Following kovacs, I'm putting `VVar` into context env when I go under binders. This avoids substitution.
|
|
|
|
## Autos
|
|
|
|
Newt has primitive auto implicits. As a first pass, higher order ones, like monad, will not
|
|
|
|
|
|
## Issues
|
|
|
|
- I should do some erasure of values unused at runtime
|
|
- I'm a little fuzzy on the "right way" to deal with constraints from unification
|
|
- I'm a little fuzzy on how much to evaluate and when
|
|
- I'm not postponing anything, and I suspect I will need to
|
|
|
|
## References
|
|
|
|
"Elaborating Dependent (Co)pattern Matching" describes building case trees. Section 5.2 has the algorithm.
|
|
|
|
"A prettier printer" was the basis of the pretty printer.
|
|
|
|
"Elaboration Zoo" was a resource for typechecking and elaboration. In particular pattern unification and handling of implicits is based on that.
|
|
|
|
"Unifiers as Equivalences" has unification with types. Look into adapting some of that (or at least read/understand it). Indexed types are mentioned here.
|