473,242 Members | 1,363 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,242 software developers and data experts.

Emulating nested function behaviour

If you know languages like Python or D you know, that nested
functions can be really handy.

Though some compilers (looking at GCC) provide the extension of
nested functions, I wonder, how one could implement an
equivalent behaviour with plain C (in this case I'm thinking of
the language I'm developing, which shall be converted into C for
target compilation). So far I didn't touch the topic "nested
functions", since I just don't see an elegant way to implement
them, but I want them, .

The problem is, that a nested functions resides within the scope
of the enclosing function and thus sees all variables of that.
Of course, if I were not seeking for portability, I could just
fiddle around with assembler on the stack. But I'd like to do as
much in C as possible.

So far the "best" solution I came up with was to create a struct
for each function, containing all it's variables:

struct _foo_variables {
int a;
int b;
short c;
/* ... */
};

static void _nest_foo_bar(struct _foo_variables * const
_foo_variables)
{
}

void foo()
{
struct _foo_variables _variables;
/* ... */
_nest_foo_bar(&_variables);
}

But this doesn't look very elegant.

By nature nested functions can only be called from within the
scope of the enclosing function. I wonder if there's a more
elegant way, to access a calling function's variables from the
called function. I presume not, but maybe I'm wrong. I'm most
concerned about the performance impact due to the need of
dereferencing stuff - most architectures are more efficient in
addressing stuff on the stack, than from arbitrary pointers,
even if they point on the stack. I don't know how good compilers
are nowadays to figure out what's going on, and optimizing this
into frame pointer relative access. Yeah, I know "premature
optimization..."

lambda expressions were implemented quite easyly using the ffcall
library; lambdas (how I specified them for my language) can't
access variables outside the scope anyway, since they're first
class objects to be passed around.

Of course I could just omit the whole idea of nested functions,
but they're so damn usefull in some occasions.

Wolfgang Draxinger
--
E-Mail address works, Jabber: he******@jabber.org, ICQ: 134682867

Dec 27 '07 #1
4 2268
Harald van Dijk wrote:
The problem isn't just that a nested function sees the
variables of the enclosing function, but that it sees the
variables of the specific call of the enclosing function, which
can be different from the most recent call if the function is
recursive.
Of course, but doing tricks like unwiding the stack would take
this into account. But C does not define anything about stacks,
and I want the generated code to be as generic as possible.
>By nature nested functions can only be called from within the
scope of the enclosing function.

Within the execution of the enclosing function. Because of
function pointers, it might be from outside of the enclosing
function's scope.
Yes of course. But the C code is supposed to be generated and not
modified directly. And all "nested" functions are declared
static, so it should be impossible to get a function pointer to
them from outside code - the code generator will definitely not
assign nested functions to function pointers that are outside
the scope of the containing function.

Well, nobody's supposed to see/touch the generated code under
normal conditions. I'm still thinking about, how I can get debug
information, which is referencing the "original" source code,
from which the C code is generated. Probably I've to fiddle
around with the DWARF data on the link level, but that's a
different problem and not related to C.

Wolfgang Draxinger
--
E-Mail address works, Jabber: he******@jabber.org, ICQ: 134682867

Dec 27 '07 #2
Wolfgang Draxinger <wd********@darkstargames.dewrites:
If you know languages like Python or D you know, that nested
functions can be really handy.

Though some compilers (looking at GCC) provide the extension of
nested functions, I wonder, how one could implement an
equivalent behaviour with plain C (in this case I'm thinking of
the language I'm developing, which shall be converted into C for
target compilation). So far I didn't touch the topic "nested
functions", since I just don't see an elegant way to implement
them, but I want them, .
[...]

I don't have any concrete suggestions, just an observation. The fact
that you're (thinking of) writing a compiler that uses C as an
intermediate language gives you an advantage: the generated C doesn't
have to be particularly easy to read, as long as it's correct.

Using C as a target language is not uncommon. I'm sure there are
existing implementations for languages that support nested
subroutines. Many of those are likely to be open source; even those
that aren't are likely to let you see the generated C code. (Eiffel
is one likely example that springs to mind.) You can get ideas from
other people's work.

You might also have better luck in comp.compilers. Note that it's a
moderated group; responses aren't likely to be fast, especially at
this time of year.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Dec 27 '07 #3
On Thu, 27 Dec 2007 21:56:29 +0100, Wolfgang Draxinger wrote:
Harald van Dijk wrote:
>The problem isn't just that a nested function sees the variables of the
enclosing function, but that it sees the variables of the specific call
of the enclosing function, which can be different from the most recent
call if the function is recursive.

Of course, but doing tricks like unwiding the stack would take this into
account. But C does not define anything about stacks, and I want the
generated code to be as generic as possible.
No, that's just it: unwinding the stack wouldn't take that into account,
because unwinding the stack would leave you at the innermost call to the
outer function. The example function I gave would generate the exact
opposite result this way.
>>By nature nested functions can only be called from within the scope of
the enclosing function.

Within the execution of the enclosing function. Because of function
pointers, it might be from outside of the enclosing function's scope.

Yes of course. But the C code is supposed to be generated and not
modified directly. And all "nested" functions are declared static, so it
should be impossible to get a function pointer to them from outside code
- the code generator will definitely not assign nested functions to
function pointers that are outside the scope of the containing function.
That will save you from a lot of problems. In that case, might I suggest
transforming what would become

int f(void) {
int data;

int nested(void) {
/* do things with data */
}
}

into

static int f_nested(void);
struct f_data {
int data;
} *f_data;

int f(void) {
struct f_data data, *prev_data;

prev_data = f_data;
f_data = &data;

/* ... */

f_data = prev_data;
}

static int f_nested(void) {
/* do things with f_data->data */
}

? This way, f_nested will have access to the data from the most recent
call to f, and even if f calls itself recursively, you won't invalidate
pointers to the local data. You just need to make sure to restore the
pointer after you return from f, that's all.
Dec 27 '07 #4
Harald van Dijk wrote:
On Thu, 27 Dec 2007 21:56:29 +0100, Wolfgang Draxinger wrote:
>Harald van Dijk wrote:
>>The problem isn't just that a nested function sees the variables of the
enclosing function, but that it sees the variables of the specific call
of the enclosing function, which can be different from the most recent
call if the function is recursive.
Of course, but doing tricks like unwiding the stack would take this into
account. But C does not define anything about stacks, and I want the
generated code to be as generic as possible.

No, that's just it: unwinding the stack wouldn't take that into account,
because unwinding the stack would leave you at the innermost call to the
outer function. The example function I gave would generate the exact
opposite result this way.
>>>By nature nested functions can only be called from within the scope of
the enclosing function.
Within the execution of the enclosing function. Because of function
pointers, it might be from outside of the enclosing function's scope.
Yes of course. But the C code is supposed to be generated and not
modified directly. And all "nested" functions are declared static, so it
should be impossible to get a function pointer to them from outside code
- the code generator will definitely not assign nested functions to
function pointers that are outside the scope of the containing function.

That will save you from a lot of problems. In that case, might I suggest
transforming what would become

int f(void) {
int data;

int nested(void) {
/* do things with data */
}
}

into

static int f_nested(void);
struct f_data {
int data;
} *f_data;

int f(void) {
struct f_data data, *prev_data;

prev_data = f_data;
f_data = &data;

/* ... */

f_data = prev_data;
}

static int f_nested(void) {
/* do things with f_data->data */
}
I was following up to the point where Harald suggested "in that case" with
the recommendation of using the most recent. Wolfgang's statement that
>so it should be impossible to get a function pointer to them from
outside code
does not eliminate the problem with Harald's recursive example where the
address is taken from /within/ the outer function, then passed to itself or
an outside function which saves the pointer, calls f and, in a nested
context, uses the earlier saved pointer.

Wolfgang, are you saying that a pointer to the nested function cannot be taken?
--
Thad
Dec 28 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Kamilche | last post by:
""" Emulating Python inheritance manually. By loading it from disk at run time, you can create new custom types without programmer intervention, and reload them on demand, without breaking...
5
by: Dave Benjamin | last post by:
I ran into an odd little edge case while experimenting with functions that create classes on the fly (don't ask me why): >>> def f(x): ... class C(object): ... x = x ... print C.x ......
10
by: Brendan | last post by:
Hi everyone I'm new to Python, so forgive me if the solution to my question should have been obvious. I have a function, call it F(x), which asks for two other functions as arguments, say A(x)...
1
by: Niall Smart | last post by:
Hi I'm trying to emulate a "following-sibling-or-self" XPath axis without using the union operator. The XML looks like this: <deeply-nested> <select> <option value="1">One</option> <option...
2
by: Bart | last post by:
Hi there, Since you've all told me that frames ar evil, I'm planning to disguard frames in favour of CSS "pseudo-frames" for my personal website. While trying to "emulate frames" (that is I...
11
by: Alfonso Morra | last post by:
Hi, I have the ff data types : typedef enum { VAL_LONG , VAL_DOUBLE , VAL_STRING , VAL_DATASET }ValueTypeEnum ;
5
by: Stephan Schaem | last post by:
How does one write an unmanaged function that perform this functionality? In short I want to turn off/on visual style in my app... Thanks, Stephan PS: two people have been looking for...
37
by: Tim N. van der Leeuw | last post by:
Hi, The following might be documented somewhere, but it hit me unexpectedly and I couldn't exactly find this in the manual either. Problem is, that I cannot use augmented assignment operators...
3
by: Dieter Maurer | last post by:
I met the following surprising behaviour .... for i in range(3): .... def gen1(): .... yield i .... yield i, gen1() .... .... 0 0 1 1
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, youll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.