I think freebasic would benefit inline functions, just like in C++
It offers so much with no drawbacks, unless you start inlining big functions of course =)
I see many people on the forums using big #macros, when inline does the same thing without being hard to debug
Inline also offers you the chance to 'return' a value
Some examples:
inline empty constructor: avoid function call for class with multiple constructors where the default one does nothing
inline getters:
they're just one line, so no need for function call
and this will still show up as "call" in debugger, which is great
Can FB do automatic inlining, considering implentations are in the modules?
Inline functions
Re: Inline functions
A kind of inlining has been on my to-do list for fbc for a long time, would be cool to have it. I was thinking that if an Inline keyword is added, it should be guaranteed inlining -- i.e. type-safe macros, not like C/C++ where it depends on compiler heuristics, attributes, optimization options etc.
It must be noted that fbc can't currently change generated code at link-time, and by design only looks at one module at a time, changing that would be difficult and, I think, wrong.
Thus, if FB allowed Public Inline procedures, the inlining could only happen in the module containing the body, and the body would have to be preserved in case it's called by other modules. Of course the programmer could work around that by putting Private Inline procedures in a header file and #including that into each module (that'd be much like C++ I think), to get inlining in all modules.
Then perhaps there's no point allowing Public Inline at all, and instead Inline could be 3rd option besides Private/Public, meaning private+inlining.
Without (or besides) that it'd also be possible to do automatic inlining based on some simple heuristic (such as every procedure with only 1 statement can be inlined). However I'm not sure that'd be wise to just do it automatically starting with some FB version, because it'd be totally unexpected by the programmers. Thus perhaps another keyword such as MayInline or something would have to be used for something like that.
I have no idea how debugging would work. It could surely show the file name/line numbers where the inlined code came from, unlike with preprocessor macros, but besides that I don't know whether there's actually a way to somehow represent inlined function calls in the STABS format.
It must be noted that fbc can't currently change generated code at link-time, and by design only looks at one module at a time, changing that would be difficult and, I think, wrong.
Thus, if FB allowed Public Inline procedures, the inlining could only happen in the module containing the body, and the body would have to be preserved in case it's called by other modules. Of course the programmer could work around that by putting Private Inline procedures in a header file and #including that into each module (that'd be much like C++ I think), to get inlining in all modules.
Then perhaps there's no point allowing Public Inline at all, and instead Inline could be 3rd option besides Private/Public, meaning private+inlining.
Without (or besides) that it'd also be possible to do automatic inlining based on some simple heuristic (such as every procedure with only 1 statement can be inlined). However I'm not sure that'd be wise to just do it automatically starting with some FB version, because it'd be totally unexpected by the programmers. Thus perhaps another keyword such as MayInline or something would have to be used for something like that.
I have no idea how debugging would work. It could surely show the file name/line numbers where the inlined code came from, unlike with preprocessor macros, but besides that I don't know whether there's actually a way to somehow represent inlined function calls in the STABS format.
Re: Inline functions
In theory it should be possible to make llvm perform an inlining optimization pass on the program after it has been linked. That is if every module is compiled to llvm bit-code, then linked by the llvm linker. However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done. Still it makes for less linking issues. We could perhaps look into it after the llvm back-end becomes stable.
Re: Inline functions
I think the simpler is that the compiler does not inline a function if (not exhaustive list):
- the function or its caller is compiled with option for debug,
- the function has a variable argument list,
- the function is recursive,
- the function is called virtually,
- the call is made via a function pointer.
- the function or its caller is compiled with option for debug,
- the function has a variable argument list,
- the function is recursive,
- the function is called virtually,
- the call is made via a function pointer.
-
- Posts: 1186
- Joined: May 08, 2006 21:58
- Location: Crewe, England
Re: Inline functions
Of course it already exists in other BASICs: DEF FN.
Re: Inline functions
I don't think you can do that, because inline functions need to be exposed to the code that uses it.gothon wrote:However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done.
It's basically just an insertion operation, probably after preprocess and just before code validation
It's definitely not possible in gcc which I've used extensively :)
I wonder why I wrote about inline operations from modules to begin with.. it does complicate things for compiler programmers and even the users themselves, since "correctly" implemented IDEs will not pick up functions hidden from you
jevans, I don't think DEF FN can inline constructors or member functions :)
Also are you guys thinking about using a more robust error/throw-catch system like there is in Java, .NET and C++?
There is good support for debugging this, in gcc "catch throw"
I'm not a big fan of throwing from constructors, since it sometimes bites you in the ass when you create objects passed directly to functions since you cannot regain the lost memory
Or, at the very least if you create 2 objects, the first constructed correctly into free store and the second throws
Is this something that is interesting for you all?
How would you implement it?
Re: Inline functions
Personally I'm not interested in adding exceptions to FB. FB is native code, the only way to add exceptions would be to do it exactly like GCC does for C++ (DWARF and/or setjump/longjump), and that comes with lots of problems (such as, being very complex and bloated, and potentially incompatible with Win32 API).
Re: Inline functions
I always thought it was simple, but I guess it's not.. :P (Just one more of those, it's so simple to use, it must be easy to implement..)dkl wrote:Personally I'm not interested in adding exceptions to FB. FB is native code, the only way to add exceptions would be to do it exactly like GCC does for C++ (DWARF and/or setjump/longjump), and that comes with lots of problems (such as, being very complex and bloated, and potentially incompatible with Win32 API).
It's very handy to use them just for setup, and for ending the program with an error, with a specialized catch clause at the end
It's really the automatic unwinding of the stack that is valueable..
Re: Inline functions
If the C emitter is used, shouldn't GCC optimize the code, inlining the functions by default?
Re: Inline functions
Nobody says that the inlined function must be visible in source form from where it is used. It only must be compiled before that use. This requires a link from the compiler to build order, and most C and GCC compilers are a bit old fashioned in this matter (probable because of the huge installed base on make-like systems). This is probably also why the inline is optional. If the original file is not compiled yet, it is not inlined, and you must manually fix/optimize your makefile.Gonzo wrote:I don't think you can do that, because inline functions need to be exposed to the code that uses it.gothon wrote:However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done.
I hope that Bjarne Stroustrup is really thinking about more modular aspects of C++ as he said in the interview after the last standard:-)
So if the inlined implementation is in the .C and not in the .H, any C that uses the inline function must be compiled after the corresponding .C, and while compiling that .C the implementation should be kept somewhere (tokenized or tree/IL form)
The non-inlined symbol is usually generated anyway, in case modules are compiled without inlining switch, and can be ejected by smartlinking (dead code elemination) if not.
And make it SEH compatible from the start. Believe me :)Also are you guys thinking about using a more robust error/throw-catch system like there is in Java, .NET and C++?
There is good support for debugging this, in gcc "catch throw"
That requires an object model where memory allocation and actual constructor are separated, a two step constructor so to say, where the first step allocates memory and calls the second step under a try catch. If it catches the exception, it frees the memory, reraises the exception and returns NULL. A static object directly calls the second level (actual) constructor.I'm not a big fan of throwing from constructors, since it sometimes bites you in the ass when you create objects passed directly to functions since you cannot regain the lost memory
Note that this only provides memory safety, not truly atomic constructors/destructors.