[Nickle]Scoping rules for declarations

Barton C Massey nickle@keithp.com
Wed, 30 Jan 2002 12:44:55 -0800


Thanks for your excellent summary.  Only comments I would
have are that

  1) AFAIK bar_expression cannot even refer to bar as things
     are currently implemented.  This is arguably just a
     bug, and should be fixed.

  2) `function' declarations aren't quite just sugar,
     because unlike case 1 above, you can refer to the name
     of a `function' in the function body.  This argues even
     more strongly that case 1 above is just a bug.

  3) Yes, you may mix definitions freely with other code.
     In fact, since definitions are expressions, you can
     write things like
         (int x = 3), (string y = "z");
     where that comma is, strangely, a comma operator.
     The principal use of this, of course, is to be able
     to write things like
         for(int i = 0; i < 10; i++)
     which work the same way as in (modern) C++.
  
  4) As discussed earlier, you have to be a little bit
     syntactically careful when doing "forward-declaration"
     style recursion.  I'd write your last example as
         int function is_odd(int n);
         int function is_even(int n) { return n == 0 || is_odd(n-1); }
         is_odd = (int func(int n) { return n > 0 && is_even(n-1); });
     as per Keith's earlier suggestion.

  Clearly, there are ugly warts here.  I'll kick around the
  `function' syntax with Keith and we'll see what we can
  figure out.

	Bart

In message <005b01c1a9b4$c20f6200$6501a8c0@meurglysvii> you wrote:
> Thanks for your answers. Let me summarize what I was
> able to guess/figure out so far:
> 
> Local declarations are self-recursive and nested (as in C):
> { /* some local scope */
>    mytype_t  foo = <foo_expression>;
>    /* <foo_expression> can refer to (but not use value of) foo
>        because it is in scope but not yet initialized;
>        it cannot refer to bar below because it is not in scope yet
>        (any reference to bar would refer to "outside" bar if any) */
>    anothertype_t  bar = <bar_expression>;
>    /* <bar_expression> can refer to (but not use value of) bar;
>        it can refer to and use value of foo: it is in scope and initialized
> */
>    <code> /* can use both foo and bar freely */
> }
> 
> Comma-separated declarations are nested also:
> {...
>   mytype_t  foo = <foo_expression>, bar = <bar_expression>;
>   ...
> }
> is equivalent to:
> {...
>   mytype_t  foo = <foo_expression>;
>   mytype_t  bar = <bar_expression>;
>   ...
> }
> 
> Function declarations are sugared versions of variable declarations:
> {...
>   mytype_t  foo(<args>) {<body>}
>   ...
> }
> is equivalent to:
> {...
>   mytype_t(<arg-types>)  foo = (mytype_t func(<args>){<body>});
>   ...
> }
> 
> Is this a correct picture of nickle local declaration rules? Is
> it possible to "mix" declarations and statements inside blocks
> (as in C99 and C++) or all declarations should come before the
> first statement of the block (as in K&R C)?
> 
> What are the rules for file-level declarations? Can I make C-style
> "forward" declarations if I am writing mutually recursive functions:
> 
> bool is_odd(int);
> bool is_even(int n) { return n == 0 || is_odd(n-1); }
> bool is_odd(int n) { return n > 0 && is_even(n-1); }
> 
> Regards,
> Sergei
> 
> 
> 
> 
> _______________________________________________
> Nickle mailing list
> Nickle@keithp.com
> http://keithp.com/mailman/listinfo/nickle