Open johnynek opened 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.
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.
Currently, there are some ad-hoc concepts in the compiler:
test
we find the last value of type Bosatsu/Predef::Test and compile that.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.