Rustic module import syntax
I think if DXL keeps things close to Rust, someday it will be easy to port code between them.
Good point, this is a vestige from "an old way" we did things when we were first prototyping (before we started mimicing Rust as much as possible). We currently use path-based resolution of modules for import, so the mechanism is slightly different at the moment, but we can at a minimum remove the unnecessary superficial differences here.
The inflexibility of our imports in comparison to Rust's was kind of unpleasant during recent work; in particular, use foo::bar as baz; would have been handy.
I think rough steps here are:
- Parse the construct
- Teach frontend routines how to traverse the symbols in a similar to fashion to imports
- Profit???
There might be challenges where currently the symbol table always knows what local symbol are types vs more arbitrary identifiers; i.e. if you refer to foo with no colon ref it's known what "kind" of thing it is (i.e. type, constant, function, etc), only when you do a ColonRef a la some_module::identifier are you unsure what kind of thing it is. I think cleaning up any of those kinds of instances will just be a positive for the frontend's making fewer assumptions.
cc @richmckeever as FYI I may start on this -- I /could/ put it behind a feature flag, but we haven't really been doing that, more treating head as "nighly" style where features get developed, so we'll just port samples in the code base over once the functionality is fully supported. LMK if you have thoughts.
Just chatted with Rich and in general it sounds good to us. Do you have examples of what fancier imports might look like? I don't know rust well.
To take an example from the repo something like:
import xls.modules.rle.rle_common as rle_common;
type DecInData = rle_common::CompressedData;
type DecOutData = rle_common::PlainData;
would instead look like:
use xls::modules::rle::rle_common::{CompressedData as DecInData, PlainData as DecOutData};
The main difference from normal Rust is that we use all filesystem-based resolution of the imported path. In Rust, at least in Cargo, crates are placed into your namespace implicitly by a metadata file. Currently we can get something kind of similar via --dslx_path flag.
Note that this will also help with workspace-level renaming when we support that in the LSP -- when we type:
type Foo = module::Foo;
It's creating something that looks like a "free variable" that actually just wants to be same as the original.
In my opinion, this can greatly improve readability of DSLX
Note also that the stdlib is getting bigger over time, and support for use will make it easier to break it into pieces grouped by functionality.