At the start of the "templates" section of the manual, it says that typed/untyped are new names for what were "historically" called stmt/expr. But then it recommends using stmt/expr if typed/untyped don't work, so they can't be exact synonyms. Also, stmt/expr are woven into the manual in the "macros" section.
What is the relationship? Are "typed/untyped" "cleaned up" versions of "stmt/expr" which are everywhere (even in "statement" or "expression" macros) softly deprecated (with hard deprecation pending more cleanup)? Or are stmt/expr "low level" versions of "typed/untyped" which will still be used in macros even if eventually superfluous in templates? In general, what is the difference and if "stmt/expr" are badly named for their current purpose, why not just introduce syntactic synonyms?
Well, I am not really sure about expr/stmt (apart what their names suggest), but the distinction between typed and untyped is pretty simple.
Sometimes you want a macro to receive a tree that can be parsed, but that would be rejected by semantic analysis. This is because you want to rewrite this tree in some other, valid, way. In this case, you do not want the compiler to do any work after parsing. This is what untyped is for.
Other times, you want to make something that needs to analyze the type of an expression. Hence the compiler should do a little more work before passing you the tree. It should be able to give it a meaningful type, hence it will have some semantic pass. In this case, you use typed.
For an example, take my pattern matching library patty. It contains a macro called match that allows you to write, for instance,
let c = Shape(kind: Circle, r: 4, x: 2, y: 0)
var res: float = 0
match c:
Circle(_, _, r):
res = r
Rectangle(w, h):
res = w + h
In this case, I need match to take two arguments: the first one is the expression that we are matching, which is typed, and the second one is the body, which is untyped.
The reason why c needs to be typed is that the macro must analyze its type to figure out, for instance, the names of the fields in order to bind them to variables. The reason why the body needs to be untyped is that it is not even valid Nim (but it is at least parsable!)
What is the relationship? Are "typed/untyped" "cleaned up" versions of "stmt/expr" which are everywhere (even in "statement" or "expression" macros) softly deprecated (with hard deprecation pending more cleanup)?
This pretty much nails it, yes.