[Nickle]Scoping rules for declarations

Keith Packard nickle@keithp.com
Wed, 30 Jan 2002 15:30:13 -0800


Around 12 o'clock on Jan 30, "Sergei Egorov" wrote:

> 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

No, foo_expression cannot refer to foo -- it's not yet in scope, the scope 
of foo appears after the expression is evaluated.  This is not the same as 
C, and violates the L->R rule that the rest of Nickle follows quite 
closely.  Of course, any other 'foo' in scope *can* be used, which 
certainly leads to a possible source of confusion.

> Function declarations are sugared versions of variable declarations:

Precisely.  Note that in an older definition of the language, this sugar 
wasn't pure -- redefinitions would locate an existing object and reuse the 
same storage.

> 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)?

Declarations are not statements in nickle, they are expressions.  As such, 
they can appear any place an expression appears, and in any mix with other 
parts of the language.  This allows things like:

	static int[*] y = (int[2]) {
	    (int l = setjmp (&c, 1)),
	    l + (func (a) { return a + ++l + x; }) (++x) + ++qq
	};

where an initializer uses a local variable that can be used in the other 
initializers.

> What are the rules for file-level declarations? Can I make C-style
> "forward" declarations if I am writing mutually recursive functions:

Sort of, but not quite.  The forward declaration isn't just a type 
definition, it also declares storage so that the second declaration
creates a *new* variable of the same time.  Instead, you need to use the 
following ugly syntax:

	int function g (int y);

	int function f (int x) {
		if (x > 0)
			return g (x-1);
		return 0;
	}

	g = (int func (int y) { return 1 + f(y); });

Or, as I said, you can use nested functions for the same effect, except 
only one of them remains visible to applications:

	int function f (int x)
	{
	    int function g (int y)
	    {
	        return 1 + f (y);
	    }
	    if (x > 0)
	        return g (x - 1);
	    return 0;
	}

Keith Packard        XFree86 Core Team        Compaq Cambridge Research Lab