Topic treated as well in the famous law of leaky abstractions : http://www.joelonsoftware.com/articles/LeakyAbstractions.htm...
All too often, this is because the programming language designers/implementors don't know what the semantics are.
Off the top of my head, the only languages I can think of with small, precisely defined formal semantics are Scheme, SML, Joy, and Prolog.
Here's the full manual including:
- the language refenrence
- all standard library functions
- the C API.
TOC: http://www.lua.org/manual/5.1/Manual: http://www.lua.org/manual/5.1/manual.html
It's very terse. The "Programming in Lua" book, by one of the authors of the language is far more friendly (an excellent book actually, the first version is available online for free: http://www.lua.org/pil/).
I ask because it's the language I'm trying to learn currently and so far it seems to have a core that's something like "Scheme with syntax" (Although I guess it's actually a lisp-2). But I don't know if it has weird edge cases that I haven't gotten to yet.
http://matt.might.net/articles/writing-an-interpreter-substi...
Short version:
* A denotational semantics is a function M : Program -> (Value -> Value) that maps a program to a mathematical function.
* An operational semantics is a relation (=>) between consecutive machine states. That is, if state => state' holds, then the machine transitions from state to state'.
* The relation in a "big-step" operational semantics need not be decidable. Big-step relations are usually recursive.
* The relation in a "small-step" operational semantics must be decidable.
* When you implement a transition relation, =>, it's usually implemented as a function. That is, if you have a relation R \subseteq State x State, you can encode this as a "transfer function" f : State -> 2^State.
* Can you convert a denotational semantics to an operational semantics (and vice versa)? Is there any value in doing this?
It depends on how you're encoding things. You might want to supply the I in I/O as an extra parameter to the transfer function.
Or, you could kick off the execution with the state containing a (possibly infinite) sequence representing all of the I/O events it will encounter during execution.
For the most part, transfer functions operate on just states.
* Can you convert a denotational semantics to an operational semantics (and vice versa)? Is there any value in doing this?
Yes, Olivier Danvy has a strong research program in this area. He has a battery of techniques that allow you to (almost) mechanically calculate one kind of semantics from another.
In many cases, calculating an operational semantics from a denotational semantics is the easiest way to prove their equivalence.
I've wondered if this is one of the things I missed by being self-taught, but I don't think most programmers working in (say) Java or Python could really follow it either.
I found "Design Concepts in Programming Languages" by Gifford and Turbak (http://www.amazon.com/Design-Concepts-Programming-Languages-...) well written and comprehensive. ( I am self taught too! :-))
Branching off the links that fadmmatt posted above, I found a booklist (http://matt.might.net/articles/books-papers-materials-for-gr...) with a PDF of Nielson & Nielson's Semantics with Applications (http://www.daimi.au.dk/~bra8130/Wiley_book/wiley.pdf). That looks good, too.
It sounds like I'm used to reading operational semantics, but have usually seen them specified in S-Expressions (as mini-interpreters in Scheme).
The real issue is that programmers new to a language are unlikely to even realize there's a semantic boondoggle in a given situation. Had they read all of the documentation, perhaps they would - but that's obviously not what most people do. Adding more pages to the documentation just to collect all semantics in one place wouldn't seem to make it more likely that a new programmer is going to read and properly understand their implications.
I don't think you can solve the problem of inexperience with additional education, but it's a common idea in academic circles.
It would be worthwhile to examine Github data to see how strong the correlation is between new languages and their adoption as a function of how large an initial codebase they come with.