Skip to content

Instantly share code, notes, and snippets.

@alexandrumc
Last active December 19, 2019 14:45
Show Gist options
  • Save alexandrumc/01c8f00e41e15ba6a541f164fd931ff3 to your computer and use it in GitHub Desktop.
Save alexandrumc/01c8f00e41e15ba6a541f164fd931ff3 to your computer and use it in GitHub Desktop.
DLang - semantic analysis on imports
module x;
import y;
/*
Semantic analysis 1 = only TOP-LEVEL declarations are analyzed
By TOP-LEVEL declarations I understand: - functions (the header of the function, the parameters and the return type;
*the body IS NOT included*)
- global variables (templates instantiations included)
- struct/classes/templates declarations
Semantic analysis 2 = solves the things that couldn't be solved in Semantic 1 (more complicated things)
(ex. templates definitions and instantiations, classes, structs etc.)
Semantic analysis 3 = the final analysis and the most complete and invasive one.
- e.g. the bodies of the functions and some properties of the templates that weren't solved in semantic 1 and semantic 2
- THE MOST IMPORTANT THING: the code on which semantic 3 is performed GETS A CHANCE TO BE GENERATED.
Now is important to understand how semantic analysis works *on imports*:
- Firstly, only semantic analysis 1 is done on imports.
- observation 1: as I mentioned before, in semantic1 the bodies of functions are not included, so that's why
there won't be an error for 'WrongCodeThatPassesLexicalAnalysis' (see y.d below) (both "dmd -c x.d" and
"dmd -c -unittest x.d" will work)
- observation 2: most of version(unittest) {} blocks are at the TOP-LEVEL; that means "dmd -c -unittest x.d" will trigger
semantic 1 on every statement that's present inside a version block (Phobos, druntime included) -> overhead
- observation 2.1 : there are still many version (unittest) in the Phobos library.
I thought that Steven’s PR removed everything, but then I verified myself and
I realized it’s not true. I tried to replace them automatically using
sed -i version(unittest)/ version(somethingElse)/g but this didn’t work
and resulted in different errors while recompiling Phobos.
The conclusion is that we must remove one version block at a time
because the code inside each version() {} has to be understood and moved correctly.
There are version (unittest) {} blocks even in the druntime, and they are
semantic analyzed (when we use -unittest) even if there are 0 import statements.
- After the semantic 1 finishes, semantic analysis 2 will begin its job on the statements that couldn't be handled by semantic1
- Now, very important, BY DEFAULT THERE IS NO semantic3 done on non-root modules => no semantic3 on imports that are not
also passed as command-line arguments.
e.g. "dmd -c x.d" won't trigger semantic3 on y.d because y is not a root module;
Now, again, very important: the special behaviour done when -unittest switch is used can be summed up as follows:
"-unittest is activating semantic analysis 3 on non-root modules (i.e. imports not given in the command line)
by considering them root modules"
Why? Because some templates from non-root modules might need code generation. Why again?
All the answers are here: https://wiki.dlang.org/Template_Instantiation_Strategy
*/
module y;
struct S(T)
{
T something;
void method() {};
}
unittest
{
WrongCodeThatPassesLexicalAnalysis;
}
version (unittest)
{
import std.uni;
import std.regex;
// other imports
// template instantiations, other things...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment