Well, yeah, but that is missing the point rather badly. There is nothing you can do in any high level language that you can't do in assembler. The only reason high level languages exist at all is to make programming less annoying.
> For many purposes, S-Expressions aren't particularly useful, because eg they don't keep track of which variables are bound where.
S-expressions are nothing more than a serialization of binary trees. There is a long, long list of features that they do not provide. Again, if you think that is relevant, you have completely missed the point.
For the record: the point, the thing that makes s-expressions cool, is that they provide a serialization of linked lists, and this serialization is super-simple, to the point where writing code in it is actually practical. They weren't designed for this. The fact that you can actually write practical code in s-expressions was a surprise, a discovery, not an invention. You can serialize binary trees as XML or JSON, and you can even use those to write code if you want to, but no one in their right might would actually do that. You would go nuts typing all those angle brackets, double-quotes, and commas. The reason s-expressions are cool is that they are parsimonious. You don't need all the angle-brackets and quotes and commas. S-expressions are actually a reasonable syntax for writing code whereas XML and JSON are not despite being fundamentally the same thing under the hood. Indeed, once you get accustomed to s-expressions, they are a superior syntax for writing code than conventional languages because they are easy to parse (no precedence rules to deal with).