Right.. "what is the definition of language"? Good point, I've taken to thinking of a _programming_ language as the embodiment of the semantics, and treating the function call API used to invoke that behavior as a perfectly valid syntax, while the grammar is implied by the combinations of calls that a user is expected to respect.
This does, indeed, differ from how many in the field think of "programming language". I evolved into this way of thinking while working with implementing programming languages and came to regard the behavior as the essential aspect. It turns out that many different syntaxes and grammars can be used as front ends to the same behavior.. which makes the particular choice of syntax and grammar feel like the interface, while the behavior is the essence.
For example, take gibberish, give it a well defined syntax and grammar, but with no meaning attached, no behavior. Others would argue "the lack of meaning just makes it a useless language, it doesn't have to be useful to anyone in order to be a language". But I feel that a definition should capture all the essential elements. True, defining language as just syntax and grammar is a valid choice, but I prefer the addition of the third element, semantics, before I consider it a _programming_ language. Also, I consider syntax and grammar in the form of an API as perfectly valid. Others argue that it's only a syntax and grammar if you have a lexical analyzer, or can state it in BNF notation, etc. That's also a perfectly valid choice, but I prefer a broader definition that doesn't focus on particular details of the form of the syntax and grammar.
To me, the behaviors are the essence, no matter what interface is used. For example, each function call of PR_DSL can be given a traditional syntactic and grammatic form. Is it now a language where it wasn't before? It's the same thing, just a different way of invoking the behavior. In fact, for the "PR_DSL__create_task( &birthFn, data)" call, I could just define the syntax to be "PR_DSL__create_task birthFn data" -- and define the grammar for the placement of the two arguments. Now is it a language? But it wasn't before?
So, in the end, there's a gray area, leaving people free to pick where in that gray region they want to draw the line..
Which brings up the question of what we call these things while talking with each other.. are you up for indulging me.. let me call them "languages" or "langlets"? proto-language would be fine, too.
Then, "programming language" would be defined as a particular kind of syntax and grammar, plus the behaviors represented by them. Meanwhile, a proto-language implements the behaviors, without saying which particular syntax and grammar front end is used. That way, multiple different syntaxes and grammars can be used as the front-end to the same proto-language, making a family of related languages. Now, comes this special thing: an interface to a proto-language can be supplied, which allows directly invoking the behavior.. But that interface, in our case an API interface, is not considered a valid front-end, so we still have just a proto-language, not a full programming language.
For me, as I read that, it feels weak to make the distinction be only the form of the front end interface. That just distinguishes a "real" programming language as one that has some chosen type of form as the interface, while a function call is not an acceptable form of interface. The main difference that I see between the front ends is that type checking and grammar checking can only be done dynamically if using the function call interface (ignoring that it's less convenient).
But, I can get over it, and go with proto-language