nostatic (or whatever)

S

Shao Miller

Good day, folks.

If we've an object which ought to contain _all_ of its relevant state
and we use a specific set of functions to deal with that object, might
it be nice to prevent those functions from accidentally including state
from outside the object?

For example, a 'nostatic' keyword (or whatever you like, as 'static
nostatic' is bound to confuse) used in:

static nostatic int foo_siblings(const struct foo * const foo_obj) {
/*
* This function cannot declare any static objects.
* This function cannot use any object identifiers
* which are not in the parameter list and are not
* in this block or a contained block.
* Type identifiers, struct/union/enum tags, function
* identifiers are fine.
*/
return foo_obj->brothers + foo_obj->sisters;
}

Could this kind of restriction help to ensure that programmers
developing the functions are bound to use only the state available in
the object?

Of course, being able to call other, non-'nostatic' functions would
easily enable one to circumvent this restriction, so maybe it wouldn't
be worth it.

If 'nostatic' functions could only call other 'nostatic' functions,
that'd limit/prevent use of the standard library, so that mightn't be
worth it.

Pick whatever keyword you like; perhaps it could be a meaning for the
'restrict' qualifier on functions? (Maybe not!)

Does anyone think it could be useful?... A means to specify that a
function doesn't "reach out" to objects beyond those that're provided to it?
 
K

Keith Thompson

Shao Miller said:
If we've an object which ought to contain _all_ of its relevant state
and we use a specific set of functions to deal with that object, might
it be nice to prevent those functions from accidentally including state
from outside the object?
[...]

These are sometimes referred to as "pure" functions.
 
B

Ben Pfaff

Shao Miller said:
If we've an object which ought to contain _all_ of its relevant state
and we use a specific set of functions to deal with that object, might
it be nice to prevent those functions from accidentally including
state from outside the object?

Do you mean the same thing as GCC's "const" or "pure" function
attribute?

`const'
Many functions do not examine any values except their arguments,
and have no effects except the return value. Basically this is
just slightly more strict class than the `pure' attribute below,
since function is not allowed to read global memory.

Note that a function that has pointer arguments and examines the
data pointed to must _not_ be declared `const'. Likewise, a
function that calls a non-`const' function usually must not be
`const'. It does not make sense for a `const' function to return
`void'.

The attribute `const' is not implemented in GCC versions earlier
than 2.5. An alternative way to declare that a function has no
side effects, which works in the current version and in some older
versions, is as follows:

typedef int intfn ();

extern const intfn square;

This approach does not work in GNU C++ from 2.6.0 on, since the
language specifies that the `const' must be attached to the return
value.

`pure'
Many functions have no effects except the return value and their
return value depends only on the parameters and/or global
variables. Such a function can be subject to common subexpression
elimination and loop optimization just as an arithmetic operator
would be. These functions should be declared with the attribute
`pure'. For example,

int square (int) __attribute__ ((pure));

says that the hypothetical function `square' is safe to call fewer
times than the program says.

Some of common examples of pure functions are `strlen' or `memcmp'.
Interesting non-pure functions are functions with infinite loops
or those depending on volatile memory or other system resource,
that may change between two consecutive calls (such as `feof' in a
multithreading environment).

The attribute `pure' is not implemented in GCC versions earlier
than 2.96.
 
S

Stefan Ram

Ben Pfaff said:
`const'
Many functions do not examine any values except their arguments,
and have no effects except the return value.

... and the return value is no effect at all.

(ISO/IEC 9899:1999 (E) does not define »effect« and neither does
ISO/IEC 2382-1:1993 nor ANSDIT, so people will have to take my
definition for it:

An »effect« is the property of an evaluation to change something.

For example, (for the sake of this example, let i be an
unsigned int value) the evaluation of »++i« has the property
to change the value of »i«; therefore, this evaluation has
an effect.

When there is no possibility of a misunderstanding, one
might also say that the effect is a property of the
expression evaluated (for example »++i«) or of its relevant
operator (for example, of »++«) or function.

A return value is a value as given by an evaluation of a
function call expression, such as »f()«. It is just a
property of this evaluation. It might be used to determine
other evaluations, which then in turn might have effects,
but it has not an effect itself.

When there is no possibility of a misunderstanding, one
might also say that the return value is given by a function
call or by the function called.)
 
S

Shao Miller

Ada already made this mistake. It forbids the use of memoing functions. These
can be more efficient implementations of true functions. It also means with a
garbage collecting malloc any Lisp style function which uses cons cannot be
regarded as a function, even though it is.

Have the language declare details of the interface and assume the implementation
obeys the interface contract. You might have something like #pragma truefunction
just before the function definition or declaration. This is a contract that the
function will return equal results for equal parameters, allowing the optimiser
to use them as invariant common subexpressions.

Sure, a #pragma could do, too. Thanks for the feedback.
 
S

Shao Miller

Do you mean the same thing as GCC's "const" or "pure" function
attribute?

...

Well, very similar to them, perhaps, but somewhere in-between. If I
understand GCC's '__attribute__ ((const))', it prevents accessing
pointed-to objects. If I understand GCC's '__attribute__ ((pure))',
it's not exactly appropriate for functions which might very well
manipulate an object.

If we have a function which adds a node to a linked list, it might
'malloc()' the node and attach it, but I was pondering the guarantees
that could be made in regards to where such a pointer might be stored;
only within a parameter object or some final target object after
following a chain of pointers (and members), for instance.
 
S

Shao Miller

China Blue Angels said:
Ada already made this mistake. It forbids the use of memoing functions.

No, it doesn't.

[...]

Well suppose 'foo(x)' actually then calls 'x->ops->foo_func(x)'. If we
want memoization, we can still hook 'x->ops'... As long as we can store
a pointer to any required memoization data somewhere accessible via
'x->...'. I didn't mean to suggest that functions couldn't do wonderful
things (including 'malloc()'), just that all object data would have to
be tied together by preventing the use of file-scope globals and
function-scope static objects.

It seems to me that you'd have a "Universe" of state space where it'd be
possible that some "galaxies" of objects might be completely and
provably separate from other "galaxies," with provably no
influence/access possible between them.

Maybe it could be useful in analysis for threads or paging or garbage
collection; I don't know for sure.
 
N

Nobody

If we've an object which ought to contain _all_ of its relevant state
and we use a specific set of functions to deal with that object, might
it be nice to prevent those functions from accidentally including state
from outside the object?

If you want Haskell, you know where to find it ;)
 
S

Stefan Ram

Shao Miller said:
it be nice to prevent those functions from accidentally including state
from outside the object?

What about:

Keep those functions in a separate compilation unit.

It is relatively easy to enforce the rule that there should
be no declarations of object identifiers with external
linkage in this unit (possibly, using a lint-like tool).

Then, forbid »#include« directives, except for certain
»pure« header files, which do not contain declarations of
object identifiers with external linkage or of »impure«
functions.

Now, functions should not be able to alter states via
identifiers with external linkage.
 
S

Shao Miller

What about:

Keep those functions in a separate compilation unit.

It is relatively easy to enforce the rule that there should
be no declarations of object identifiers with external
linkage in this unit (possibly, using a lint-like tool).

Then, forbid »#include« directives, except for certain
»pure« header files, which do not contain declarations of
object identifiers with external linkage or of »impure«
functions.

Now, functions should not be able to alter states via
identifiers with external linkage.

That seems pretty reasonable. I guess having "help" in C itself is
hardly worth the complication(s), and a strategy like the one you offer
above is indeed simple enough for a team of programmers to adhere to
(including a check step using a tool). Thanks for the feed-back!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top