perf: fix polynomial decoding induced by `#import`s
Motivation and Context
Related issue: #2153
Related slack thread: https://tezos-dev.slack.com/archives/C04EM6W78A0/p1710346643230689
Currently we have the following build process:
- The build system builds each file independently (ordered topologically based on the dep graph)
- The preprocessor expands
#import "<file>" "<name>"
tomodule <name> = Mangled_module_<file>
- The build system links modules by defining
module Mangled_module_<file> = struct <file contents> end
as a 'header', creating a single largeAst_typed
module
For every module <name> = Mangled_module_<file>
, the type checker has to encode the signature of <file>
to be added into the Context
and then must decode the signature of <file>
from the typer's IR signature to Ast_typed.signature
.
The problem is that module
aliases are by default public
, meaning that the signature of the #import
is exported.
This can result in nasty polynomial behaviour in larger projects where files are nested by depth d
and have common / repeated imports: O(N^d L)
where N
is the number of files in the project and L
is the upper bound on lengths of signatures
Description
The fix is to:
- Adding a
D_import
declaration to Ast_core.declaration - Modifying the nanopasses to transpile:
- JsLIGO: import = <Mangled_module> ~> D_import (Name, Mangled_module)
- CameLIGO module = <Mangled_module> ~> D_import (Name, Mangled_module)
- The type checker will type the import just like a module, but it won't add the alias to the signature of the module nor will it need the decode the signature of the Mangled_module
- Add a linking phase to the build system that converts imports to module aliases
This is a breaking change on the current behaviour (imports are exported by default). To mitigate this, imports can be export
ed:
(* cameligo *)
[@public]
#import "foobar.mligo" "Foobar"
// jsligo
export #import "foobar.jsligo" "Foobar"
For reviewers: I've tried to mostly split commits by:
- compiler changes
- lsp changes
- test changes
Once approved, I'll squash and merge :)
Component
-
compiler -
website -
webide -
vscode-plugin -
debugger
Types of changes
-
Bug fix (non-breaking change which fixes an issue) -
New feature (non-breaking change which adds functionality) -
Breaking change (fix or feature that would cause existing functionality to not work as expected) -
Performance improvement (non-breaking change that improves performance) -
None (change with no changelog)
Changelog
perf!: fix polynomial decoding induced by #import
s
Checklist:
-
If a new syntax has been introduced, put a message on slack ligo-lsp -
Changes follow the existing coding style (use dune @fmt
to check). -
Tests for the changes have been added (for bug fixes / feature). -
Documentation has been updated. -
Changelog description has been added (if appropriate). -
Start titles under ## Changelog
section with #### (if appropriate). -
There is no image or uploaded file in changelog -
Examples in changed behaviour have been added to the changelog (for breaking change / feature).