This reminds me of a great talk, Constraints Liberate, Liberties Constrain, by Runar Bjarnason. [0]
Useful abstractions necessarily impose restrictions compared to a free-form 'all powerful' approach, but abstractions make it easier to perform/compose meaningful operations.
A compiler can reason about an AST far more easily than it can reason about a machine-code sequence, for instance. A compiler typically converts from AST to machine-code pretty late in the game, as you want to take advantage of the utility of the abstraction, not the unlimited power of directly working with instructions.
Useful abstractions necessarily impose restrictions compared to a free-form 'all powerful' approach, but abstractions make it easier to perform/compose meaningful operations.
A compiler can reason about an AST far more easily than it can reason about a machine-code sequence, for instance. A compiler typically converts from AST to machine-code pretty late in the game, as you want to take advantage of the utility of the abstraction, not the unlimited power of directly working with instructions.
[0] https://www.youtube.com/watch?v=GqmsQeSzMdw