Re: Special Interest Groups - HTTP/CGI and SMTP/MIME
Ger Hobbelt <[email protected]>
| Newsgroups | gmane.mail.spam.crm114 |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Mar 17, 2009 at 12:03 AM, Chris Babcock <[email protected]> wrote: > Some flavor of scoping or notion of name spaces will have to happen > before it's feasible to develop library code... and candidly, that's > what I spend most of my time doing. I've got a dirt simple SMTP client, > some basic CGI stuff and an HTML template driver. It's surprisingly few > LOCs, but it's enough that I've put off upgrading to BlameBarack. > > I'm kind of hoping that the scoping mechanism in the main branch is > something really novel and idiomaticly CRM. Since you can syscall > labels, using syscall v. call isn't really that big of a deal. If > declaring namespaces were explicit, though, existing code would still > work and accessing libraries would be transparent. The issue would then > be finding an idiomatic way to declare the namespace. Hmmm... so you want something idiomatically CRM, huh? Well, for 100% backwards compat scoping, one could extend the grammar either way: 1) add a <scope> attribute to the 'call' command - when specified, it'd act like my current local-scope-push-on-call approach, as part of definition would be the adage that such a 'scope' would automatically 'pop' once you hit the matching 'return' command. idiomaticly CRM, yet still intuitive, I'd say. It requires library users to be on their best behaviour though, as the *caller* mustn't forget to add that <scope> attrib when calling 'third party' crm script library code (or at least any library routine which is to be treated as a 'black box', variable-instantiation wise. 2) what I call 'The VB Way' (keep those flight sickness bags at the ready, chaps!): CRM has this Saturday Night Special in the language called 'window', which does something truely wicked when occurring as the first non-brace command in a CRM114 script. Gives me the 'option explicit' / 'option strict' feeling. Now imagine this... option <scoped> as a special instruction at the start of crm114 scripts which desire scoped variables. Of course, it would only work really well when library code assumes this option set or unset the way the main script has it. Hrrrrrrrrrrrrrrrrrrrrr. For those who like 'we'll fix it in the mix' quick readiness over relatively slow, serious design. 3) going scoping all the way by taking <1> for a ride: instead of limiting scope level boundaries occurring at call/return milestones at run-time, one could instead consider every pair of curly braces as a scope level push/pop candidate a la 'C' and it's relatives. This can be done two ways: 3a) 'push' a scope level by explicit command, e.g. { scope ... ... # crm code with 'local' scope. } the 'scope' command should occur within the opening curly brace level to which is applies, to imitate match/eval/liaf/etc. behaviour which the next outer pair of curly braces as edges too, or: 3b) be a little sneaky, knowing that the opening curly brace is just another command in crm114 script, which can accept <...> and other attributes (it's in the command definitions table; minor change otherwise), so an explicit scope can be declared thus: { <scope> # 'scope' is an *attribute* of the '{' command! ... ... # local-scoped crm code } 4) the commandline equivalent of the 'option explicit'-flavor is, of course, done by adding an extra commandline argument, such as '--scoped-vars' to your crm114 invocation and ta-da! suddenly the executed script uses variable scoping (call/return or curly-brace-pair flavor?) And then we should reminisce on multiple scope levels: while not residing in an inner local scope, instantiations should happen in the next outer scope (cf. 'C', pascal, and all other mainstream languages, == current GerH call/return scope approach). When you use attributes to signal scope-push, you can use the same mechanism for those nasty coders who crave to instantiate 'true globals' from within deep local scope levels - even though decades of software development has shown such code is a maintenance nightmare. similar to this 'C' code: void f_y(void) { extern int global_var; global_var = 666; } The 'outer scope' rule would make variable instantiation behave more rationally and more like Pascal offers in constructs such as: function outer() var o: integer; procedure inner() (* 'C' doesn't know function nesting; pascal does *) begin o := 42; end; begin (* code for outer() *) o := 0; inner; return o; (* returns 42 *) end; Would be nice to hear what Bill, Nick and Kent have been discussing about this issue out here in the open. Which of the above wheels are re-invents of mine, fellas? ----------------------- post scriptum: At the moment my preference would be 3b) but that only because of it's scary-cuddly factor as it nicely matches the score of rest of the language in that regards, at least to the taste of this jury member. Option 3a) may be looking 'more professional' but it's just begging to be abused (and given some code I've seen, it will) as you plonk such a 'local scope push' instruction right smack in the middle of a command sequence, which has the effect of global vs. local var instantiation within a single brace block, e.g.: { isolate ... # this is an instance in 'outer scope' ... # more code in outer scope # abusive coding $1: push scope halfway down the road: scope # push a local scope for this curly brace pair isolate ... # local scope instantiation ... # yada yada # even more abusive, yet legal $2: push ANOTHER scope! scope # push a local scope for this curly brace pair isolate ... # local-local scope instantiation ... # yada yada } # pops both local-local and local scope pushed above The nice thing about 3b) is that you cannot do abusive $2, nor can you do $1. And when you want this sort of thing at call/return level, yet don't want to bother the caller, yet have the callee handle it on its own (thus restricting impact to smallest possible code unit), write this, assuming 3b) syntax: :func_label: (:args:) { <scope> # push that local scope ... .... return # watch it! this does NOT pop the scope yet! } # this brace does! Because *now* you are leaving the # curly brace block. Beware: trap handling code, i.e. where a catch-all trap sits at the end of your script, outside all those curly brace blocks, implies that SUCH traps won't have access to your local-scope var instances anymore; for that to happen, you must place the trap code within that same brace block, which is an appropriate coding style anyway. !!! Current GerH scoping rules 'pop' on the 'return', so _that_ means those 'on error abortus provocatus' catchall traps at the end of scripts _do_ have access to the innermost active local scope from the time of the fault. Which is counter-intuitive in a way, yet intuitive in another. That's the consequence of going for scenario (1) (call/return = scope), instead of the 'enhanced' curly-brace (3) style. Style (1) was easier to code into the existing engine than any of the (3) styles, 's all. And if you take the (3) scoping idea and take it all the way, then there's a lot to say for the pascal scope nesting rules, which is more advanced than C's as it includes function/procedure nesting: this means my current thought is that, ideally, you can 'scope' both variable instantiation AND *code labels*, so that one can create jump labels and thus routines which are hidden to the 'outside world'. In C such is hackishly resolved through the use of the 'static' attribute with function declarations, while pascal supports function nesting, so that :inner: in the example below would NOT be callable from outside the :outer: braces-based scope: thus multiple library scripts can be safely included in your code, where you don't risk silent label collisions like you have today: :outer: { <scope> .. ... call /:inner:/ ... call /:inner:/ ... return # sub-function: only accessible from within the :outer: scope! :inner: { <scope> # act like pascal: one scope for each function, at ANY # nesting depth ... ... ... return } # pop :inner: scope ... } # pop :outer: scope This would make true library implementations feasible in crm114 script. Without the label scoping, you'd still risk collisions! C has this issue; C++ introduced the 'namespace' to cover this up, other languages have different means to solve this issue (pascal function nesting is the neatest solution IMO as it's the only recursively congruent construct I've seen so far. >From a language engine run-time standpoint you could do this in both call/return or curly-brace scoping rule style (though the parser will require some adjustments); from a language _definition_ PoV you must bind the scope boundaries to the curly braces to keep it grokkable for homo sapiens. While out-of-curly-braces-scope traps which catch faults are a bother scope definition-wise, either way. -- Met vriendelijke groeten / Best regards, Ger Hobbelt -------------------------------------------------- web: http://www.hobbelt.com/ http://www.hebbut.net/ mail: [email protected] mobile: +31-6-11 120 978 -------------------------------------------------- ------------------------------------------------------------------------------ Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are powering Web 2.0 with engaging, cross-platform capabilities. Quickly and easily build your RIAs with Flex Builder, the Eclipse(TM)based development software that enables intelligent coding and step-through debugging. Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com