johnynek / bosatsu

A python-ish pure and total functional programming language
Apache License 2.0
224 stars 11 forks source link

changing how we compile/render values #1115

Open johnynek opened 8 months ago

johnynek commented 8 months ago

Currently, there are some ad-hoc concepts in the compiler:

  1. testing: when we run test we find the last value of type Bosatsu/Predef::Test and compile that.
  2. compiling: we just convert every value in the compiled code into the underlying language.

Instead, we could just treat test, main, or json values as any other kind of value. To compile to python or run, we would require the value we are running. To test we would accept a list of values (package::name) to compile into a test.

With this picture, we can do tree shaking and build up from those values down. We don't need to compile all transitive code to build our main, or run our tests. Just the specific tests we are going to run.

This also allows us to be more regular: any value we are going to use must be exported, since it is visible outside the package. Secondly, we can make it an error to define values we don't export or use in an exported value. This can help us catch untested or unused code.

johnynek commented 8 months ago

One idea would be to introduce types into Bosatsu/Predef:

struct PackageTest(tests: Test)
struct PackageMain(main: List[String] -> IO[E, A])

then have a lint that each package exports at most one value of each of those types. Then, use those values for automatic discovery.

johnynek commented 7 months ago

I don't think types add anything to the picture here.

We could just use names. If you export test of type Test that's the test. If you export a value of name main that is the main value. If the type of the value is IO we run it, if it is type Json[a] we render it as json if we can render a into json or error. Otherwise we render the type into a String.

This same algorithm could be used by a repl or notebook.