Monthly Archives: August 2013

Following API changes

PureBasic uses a commandset built on top of the OS API, using generic commands to abstract it from you, the developer. One of the most daunting (and boring) task for us is to follow underlying API changes. A famous example was Cocoa support replacing old Carbon API on PureBasic for OS X. Another one is the DirectX11 support for the Sprite/Screen library on Windows. Linux isn’t left behind, with the recent GTK3 support for the whole commandset. All this requiers a lot of work, new knownledge to learn, and tons of testing, just to provide functionnalities which already work in the current API. From the PureBasic developer point of view, there is nothing fancy as the commands works as usual, only the implementation under the hood has been completely reworked. That’s one of the great strength of PureBasic: you can upgrade your program without worrying it about the technology used behind by just using a new version. OK, you will probably have some adjustements to do here and here, but it’s really nothing compared to migrate a whole program from one API to another.

Which brings us to a somewhat recurrent issue with PureBasic upgrade: commands are sometimes renamed, changed, or even removed. It often makes the developer angry as a working code needs to be modified to run again with the new version, and we don’t like to change working code. Agreed. But I would like to explain why it happens, and why it is important for PureBasic future. One important thing to understand: we don’t change the commandset unless it’s really necessary. It’s not our goal to mixup the whole stuff only to bother you. That said, the technology is always evolving and an high level programming language like PureBasic needs to follow the evolution as well. If not, it will be left behind, and a new language, using more modern API will take over. Let me use the sprite library as an example to illustrate my thoughs:

– API designed on Amiga in 1998 with no 3D acceleration. Was quite simple: sprite only, no zoom, no rotation, and many software only routines.
– Later, with DirectX7 on Windows, we got some 3D accelerated functions for some cards, so we added the ‘sprite3d’ library to support it. It was optional, as it didn’t work everywhere. That made the sprite lib a bit more hard to use, as you had to create 3D sprite using a real sprite with texture mode. DirectX7 mainly worked with 2D acceleration using DirectDraw, so we couldn’t switch to full 3D
– Nowaday DirectX9/DirectX11/OpenGL offers much better support for 3D only sprites, and 2D acceleration is not supported anymore. So all the sprites are now natively in 3D, even if we use it in 2D mode. What the purpose of having a ‘sprite3d’ lib as regular sprites are 3d anyway ? This one was obsolete, so we had to remove it to cleanup the library and have easier sprite handling, for you and for newcomers.

A new language won’t even think about separating sprite in 2 libs as it makes no sens: all is 3D now, even cheap phones handle its GUI in 3D mode. That was legacy and if we want to have PureBasic around in the future, we have to think ‘new’, and adapt the current commandset to new technology, even if it slightly breaks code. If we stick with older functionalities/design for compatibility sake, we will be slowing dying. Indeed, old PureBasic versions are available in the museum section of your online account, if you just need to do maintainance on a software.

Getting the best out of the IDE when using Modules

Since the last beta version (5.20 beta8) the IDE finally has support for Modules as well (AutoComplete, QuickHelp, ProcedureBrowser etc). Please test these features well, as it was quite a change in the IDE to implement this. Now, to get the best experience when using the IDE and Modules together, there are some simple rules that have to be followed. I will explain them below. But first, let me explain why these limitations exist.

As the AutoComplete feature became smarter and more helpful in past versions, it had to grow from a simple scanning of the source for strings into a full grown analysis of the source code. This is especially required for modules, because the IDE needs to know what procedures/constants/structures are exposed from each module in order to present the correct choices in AutoComplete. So the IDE in essence needs to understand your code. The best way to fully understand code is to compile it. The IDE does not actually compile the code for the following reasons:

  • Speed: The AutoComplete feature cannot introduce delays because that would make it unusable. So compiling the entire code from beginning to end is not an option.
  • The code is usually not compilable anyway: Remember, the purpose of the IDE is to edit code. While you edit a line, it will be in a state that cannot be compiled most of the time. In fact, if you look at all characters typed in a source code, the instances in which that typed character puts the source in a compilable state are rather rare compared to those that put it in a state with errors (from a compiler perspective).
  • There are IDEs that actually have a builtin compiler that can tolerate this and still compile the code. Eclipse is such an example. However, writing something like that is quite complex and is actually harder for PB because of features such as macros and compiler directives.

Instead, the IDE tries its best to (quickly) understand the code without a full compilation. For that, it parses the code and extracts all information that can be understood without context (from a single line of code) into an indexed form for fast search. This organization has the benefit that if a line of code is changed, only this line needs to be parsed again and not the rest of the code which is quite fast. Then when the type of a variable is needed or something like that, the IDE searches through this indexed data to put it in the proper context to answer the question. So it is not a full compilation, but rather a “fuzzy” analysis of the code. In essence, the IDE collects the information it can understand, and stuff that only a compiler would know (like what an expanded macro would look like) is ignored.

So how does this affect Modules? One thing that the IDE does not do is resolve which source file is included where in the final program. It only looks at each source file individually. This was no big limitation before modules existed, but with modules it means you have to follow some rules so the IDE understands where a module begins and ends and what it contains.

These are the rules:

  1. The entire DeclareModule/EndDeclareModule block should be in the same source file.
  2. The entire Module/EndModule is best also written in a single file, but it does not have to be the same one as the one that contains the DeclareModule
  3. At least the file containing the DeclareModule block should be included in the Project and scanned for AutoComplete. You don’t have to include the actual module implementation since the stuff in there is not visible on the outside anyway.
  4. If you use UseModule, all modules that are open within a source file should be opened within that source file. The best was is simply to have the UseModule calls right at the top.
  5. Don’t hide the essential module commands behind macros. The IDE does not expand macros so it will not know that the keywords are in there.

The explanation is rather simple. Consider this code:

DeclareModule Foo
  XIncludeFile "FooDeclaration.pb"
EndDeclareModule

Since the IDE only looks at each source file individually, it does not know that the contents of FooDeclaration.pb are part of the module declaration. So the IDE sees an empty Foo module, plus a file FooDeclaration.pb with stuff that is outside of any module.

In the same way, if you have a UseModule call outside of the current source file, the IDE does not know that stuff from the opened module is available while you edit your file and therefore cannot help you with AutoComplete in this case.

Other languages enforce such rules on the compiler level (one class per file etc). We chose to not limit the compiler in this way so you can organize your code as you like. And you don’t have to follow these rules to use the IDE. It just cannot be as helpful as it could be if you don’t. Anyway, in my opinion these rules also make sense from a code organization standpoint so i don’t think it is that hard to follow them.