Collecting variables

While I have little time for QTX until the first quarter of 2015, I did sit down for a session yesterday evening. This time I implemented the variable collection methods – which is a huge distinction between basic and pascal.

In the basic language you have no restriction regarding where you define a variable. Using the “dim” statement you can pretty much define variables throughout the sub routine — while under object pascal you are expected to clearly define all variables as part of the procedure interface.

So the basic parser now collects and registered variables, and the code emitter ejects them according to pascal standards.

So when compiling the following:

module cool

rem this is a remark
rem this is a second remark

public class myclass(TObject)

   private field temp as integer
   protected field text as String

   private sub firstproc(byval a as String, byval b as integer)
     let temp=1200
     let text="this is a nice string"
   end sub

   public sub secondproc(byref a as String, byval b as integer)
     dim Jalla as String
   end sub

   public function myfunction(byval a as String, byval b as integer) as boolean
   end function

end class

The code emitted looks like this:

unit cool;

interface

type
  myclass = class;

  myclass = class(TObject)
  Private
    temp:integer;
    procedure  firstproc(const a:String;const b:integer);
  Protected
    text:string;
  Public
    procedure  secondproc(var a:String;const b:integer);
    function myfunction(const a:String;const b:integer):boolean;
  end;

implementation

//#################################################################
// Implementation for class:myclass
//#################################################################
procedure myclass.firstproc(const a:String;const b:integer);
begin
  temp:=1200;
  text:='this is a nice string';
end;

procedure myclass.secondproc(var a:String;const b:integer);
var
  Jalla:String;
begin
end;

function myclass.myfunction(const a:String;const b:integer):boolean;
begin
end;

end.

This got me thinking about possible optimization techniques. At the moment the parser organize the code using LDEF, which is a class hiearcy designed to describe a whole program. I have not yet added unique identifiers to the various elements — but this is what I’m thinking about doing.

If all parsed elements have a unique URI (universal resource identifier), being able to optimize the final code would be much easier. And URI in this case would mean a logically derived, human readable, identifier. For instance a variable of a procedure would have an URI as such:

unit1.TMyClass.ProcName.x
unit1.TMyClass.procname.y
unit1.TMyClass.procname.aName

Why is this important? It’s important because it allows us to query the LDEF structure in a logical manner. Asking for instance LDEF to give us all the variables for a procedure would be easy.

The LDEF classes could for instance have functions like:

with mprogram.units.objectOf('unit1') do
with classes.objectOf('TMyClass).objectOf('someProc') do
if variables.collect(mVariables,vuLocal) then
Begin
  try
    for x:=0 to mvariables.Count-1 do
    listbox1.items.add(mVariables[x].exportedName);
  finally
    mVariables.free;
  end;
end;

The above shows how to drill down into the program->unit->class->method structures and extract the list of defined variables for a method (within the local scope, meaning only variables allocated for the life-cycle of a call). How the code emitter deals with this data would be individual, depending on the emitter type. JavaScript may want to initialize the variables (handy to also set type) to zero or “” for strings. If the code emitter targets freepascal then you may want to initialize pointer types to NIL (or at least have that as an option).

This means we could do optimization such as allocating all variables for a class on creation. This would mean faster execution time for all methods in that class. In some cases it could also be possible to pre-allocate most (if not all) variables used by all classes in a whole unit (per instance of-course) when the program starts up. This would produce a very substantial speed boost. So when you create an instance, the code automatically initializes memory for every field + all variables used by the whole class.
Naturally, only some class types would be suitable for this particular optimization, but it would mean a lot of difference to those written in vanilla pascal (no dynamic allocation of objects, no pointers etc).

Another type of mild optimization would be to isolate variables in a record. So if you have used say, 20 variables in a procedure – we could allocate the memory this represents as a single alloc-mem and read/write directly to that memory via offsets.

So instead of this:

procedure TMyClass.SomeProc;
var
 a,b,c,d,e,f,g: Integer;
 M:ShortString;
 G:Int64;
begin
  a:=1;
  b:=2;
  G:=16765;
end;

The generated code could be reduced to (pseudo):

procedure TMyClass.SomeProc;
var
 mData:PByteArray;
begin
  mData:=allocMem(VAR_SIZE_TOTAL);
  PInteger(@mData[0]):=1;
  PInteger(@mData[4]):=2;
  PInt64(@mData[156]):=16765;
  freemem(mData);
end;

This could be further made “human readable” by straight out isolating it in typed-records, which may seem like a waste of time but could (we are talking research here after all) have some debugging sense to it. Easier to figure out where you went wrong in a typed setting, were a range exception would be thrown if you overwrite a shortstring buffer or try to stuff an int64 into a 32 bit integer.

While records are cool, the fastest optimization for local variables (depending on their type again) would be to completely decouple the structure and simply ascend the pointer into the buffer:

procedure TMyClass.SomeProc;
var
 mData:PByte;
begin
  mData:=allocMem(VAR_SIZE_TOTAL);
  PInteger(mData)^:=1;
  inc(mData,4);
  PInteger(mData)^:=2;
  inc(mData,148);
  PInt64(mData):=16765;
  freemem(mData);
end;

We could also, if we so desired, do stuff that is quite unheard of. For systems with extreme memory conditions (like the Raspberry PI) we could opt to use disk rather than real memory. Which means I would write a new memory manager which maps a disk file to memory (memory mapped files). Performance would be terrible ofcourse, but depending on the application it could be a life-saver. Delphi has been used in internet-search engine technology where 32bit memory ranges (and disk file sizes) quite simply were to small. A search-engine crawler is one type of service where speed comes seconds place to getting the job done correctly, even if it’s 10 times slower than ordinary memory allocations.

This is probably one of the few places where procedure attributes does more than look cool. Finally a practical example of using them under object pascal (or object basic for that matter):

module cool

public class myclass(TObject)

   private field temp as integer
   protected field text as String

   [memoryModel="preAlloc"] ' all variables allocated in one chunk
   private sub firstproc(byval a as String, byval b as integer)
     let temp=1200
     let text="this is a nice string"
   end sub

   [memoryModel="memorymap"] ' heap allocated and mapped on disk
   public sub secondproc(byref a as String, byval b as integer)
     dim Jalla as String
   end sub

   public function myfunction(byval a as String, byval b as integer) as boolean
   end function

end class

In the example above the “pre-allocated” would instruct the code emitter to generate code which pre-allocates all variables as a single memory block. The second procedure is marked as mapped, and could in fact allocate it’s memory on disk, using a memory-mapped file technique. This would be suitable for procedures that target memory beyond the 32-bit range. A locking mechanism would probably be the best way to go. Much like C#’s fixed syntax, which prevents the garbage-collector and heap manager from moving memory around while you access it with pointers:

fixed ( *PTR = (byte)&FLargeByteArray )
{
//Do something with PTR which is of type PByte into a huge array
}
[/CODE]

For object pascal this could be made an extension to the “with” syntax:

[memoryModel=”memorymap”]
procedure TSomeObject.SomeProc;
var
mArray: packed Array[1…26000000] of byte;
mPTR: PByte;
begin
with fixed(mArray,mPTR) do
Begin
//do something with mPTR
end;
end;
[/CODE]

And also under object basic:

[memoryModel=”memorymap”]
private sub someProc
dim mData as byte(26000000)
dim ptr as reference to byte

with fixed(mData,ptr) do
let ptr = 12 ‘set first byte to 12
incr ptr, 12000000 ‘jump forward 12000000 bytes
let ptr = 13 ‘set byte #12000001 to 13
end

end;
[/CODE]

Some control issues would have to be adressed (locking only a segment of the memory, not the whole payload). This could be a parameter to the fixed keyword, with a syntax such as: with Fixed(Array,IndexPTR,StartByte:Int64,Length:NativeInt). But perhaps a more ad-hoc treatment is in order:

[memoryModel=”memorymap”]
procedure TSomeObject.SomeProc;
var
mArray: packed Array[1…26000000] of byte;
mPTR: PByte;
begin
with fixed(mArray,mPTR) do
Begin
lock(mArray,1024);
try
//do something with mPTR
finally
unlock(mArray);
end;
end;
end;
[/CODE]

Or, just to leave no stone unturned — make use of steams on the level of the language itself, as opposed to RTL:

[memoryModel=”memorymap”]
procedure TSomeObject.SomeProc;
var
mArray: packed Array[1…26000000] of byte;
mAccess: TLockStream;
mWriter: TBinaryWriter;
begin
with fixed(mArray,mAccess) do
Begin
if mAccess.getWriter(mWriter) then
Begin
try
mAccess.seek(12000000,soFromCurrent);
finally
mWriter.free;
end;
end;
end;
end;
[/CODE]

In the above example, the syntax for “with fixed” would be:
[pre]
with fixed(typed array, mAccess:TStream) do
end;
[/pre]

The control stream would be automatically destroyed when the code goes out of scope (when the CPU hits the “end” of that section).
Now, a lot of this may seem useless at first, nut consider the fact that a lot of applications deal with huge amounts of memory for some processes. Adobe Photoshop has solved this by using a scratch-file (and actually a scratch-disk for high-end mac’s). Having support for this straight in the language would be interesting to say the least.

Object Pascal could indeed be transformed into a very modern, very practical language. Actually it wont take much in order to completely transform our time-less and classical programming language into THE processing language par excellence. And we dont need to add strange, dot net inspired elements either (generics stands out like a sore thumb, with it’s C++ background). There is ample room to expand on the classical object pascal syntax to provide more substance.

Advertisements

Compile Visual Basic to Object Pascal – Proof of concept

I have been talking a lot about the Quartex IDE – to which this website is dedicated. But a topic that I have yet to fully explain and demonstrate is the compiler technology. Especially how you can compile one language into another language without actually building any binaries.

This type of compilation is called source to source compilation. It may sound easy, I mean – all you have to do is translate from A to B right? Well if only that was the case! No I’m afraid it’s far more complicated, in fact almost just as complicated as writing a real-life compiler which emits machine code. The only difference between my source to source compiler and say, Delphi’s compiler or C++ builder, is that the final step of the compilation process where both Delphi and C++ builder omits machine code and link everything into a single executable – is not present.

Smart Mobile Studio is a source-to-source compiler toolchain

Smart Mobile Studio is a source-to-source compiler toolchain

But the rest of the compilation process is very much required, which includes parsing, tokenizing and analyzing every single character of your code. And once recognized and broken down into symbols and expressions (which is probably one of the most recursive tasks you can do on a computer) – the object hierarchy built in memory is handed over to a code emitter which generates source-code for another language from this.

Compiling basic into object pascal

Sounds nuts right? Well it may not be so crazy as some may think. Object Pascal has one massive advantage over other languages in that you get the best compiler for free: namely freepascal. You may believe that the Delphi compiler is the best, but that is not the case. When it comes to hard-core optimization FPC beats Delphi every single time, be it object creation, numerical operations, memory access — every aspect you can imagine, freepascal does it better. Delphi doesn’t even get a vote on the mono compiler stats (comparing mono C# code when compiled to a single native executable); the only object pascal compiler to give mono and C++ a run for their money is FPC.

I do have a bit of mad genius in me

I do have a bit of mad genius in me

As the name implies, freepascal is free in the broadest sense of the word. You can download it, use it, alter it and re-distribute it. As long as you respect the fact that you cannot re-brand it (remove names of the true authors or change the name of the product) – you are free to ship FPC with your own projects.

This means that source-to-source compilation suddenly becomes very interesting (!) By transforming my object basic (read: visual basic on steroids) dialect into object pascal – Quartex IDE is able to produce rock solid, state of the art executable programs. So my compiler deals with syntax and all the other stuff, and freepascal takes care of the rest.

QTX Basic -- the most powerful basic you will ever find

QTX Basic — the most powerful basic you will ever find

The end result is good news for both Delphi and the freepascal organization. There are roughly 2 million object pascal users in the world — but there are some 20+ million basic developers (source: Microsoft Visual Studio Unleashed) and the number is growing! The majority of these developers are bound to the dot net framework without any real alternative. And basic users tend to look at object pascal as either to technical (pointers, inline assembler, records, no garbage collection) or quite simply irrelevant in their IT infrastructure.

Providing a path for them to not only benefit from object pascal – but also become exposed to just how fantastic object pascal is – means that more people will be attracted to our language, with a natural “next step” to investigate freepascal and Delphi.

Proof of concept

While I would love to post a preview of the IDE, I feel I would be doing you a disfavour at this point. The core functionality of the IDE is nearing completion, but there is still a lot of detail and features that are not implemented yet. The engine is running, but you dont want to test the car until it has seat-belts and all the fancy widgets in the dash works as expected. But the moment we have an alpha — you can trust me that a demo will be available right here.

Well, today I compiled my first basic program into object pascal (!). Still have a ton of expression classes to write, but here is the input basic unit:

module cool

rem this is a remark
rem this is a second remark

public class myclass(TObject)

   private field temp as integer
   protected field text as String

   private sub firstproc(byval a as String, byval b as integer)
     let temp=1200
   end sub

   public sub secondproc(byref a as String, byval b as integer)
   '
   end sub

   public function myfunction(byval a as String, byval b as integer) as boolean
   '
   end function

end class

Which my compiler parsed, tokenized and transformed into the following pascal code:

unit cool;

interface

type
  myclass = class;

  myclass = class(TObject)
  Private
    temp:integer;
    procedure  firstproc(const a:String;const b:integer);
  Protected
    text:string;
  Public
    procedure  secondproc(var a:String;const b:integer);
    function myfunction(const a:String;const b:integer):boolean;
  end;

implementation

//#################################################################
// Implementation for class:myclass
//#################################################################

procedure myclass.firstproc(const a:String;const b:integer);
Begin
  temp:=1200;
End;

procedure myclass.secondproc(var a:String;const b:integer);
Begin
End;

function myclass.myfunction(const a:String;const b:integer):boolean;
Begin
End;

end.

Stuff like forward declarations is automatically generated since Basic has a completely different concept of scope and visibility. Under object pascal you can only see backwards but not forward (hence we use forward class declarations to compensate). But basic has no such limitations since the compiler does symbol validation at the end of the cycle.

I write my code in Delphi and later port it to FPC/Lazarus

I write my code in Delphi and later port it to FPC/Lazarus

Now this may look like a simple 1:1 translation, where you just scan through the lines and replace stuff. But that is not the case. In fact just to translate the expression “temp:=1200” there is quite a bit of code required. “temp” is a class field, which has to be recognized as such. Also the datatype is of type integer. This means that whatever source data is assigned to that field – must match the datatype. Also, the type of assignment has to be dealt with. In this case it’s a constant assignment of type TQTXExprConstInteger.

References better than pointers

In Delphi we are used to the same level of access as C++ and Assembly programmers enjoy. We use pointers, we write inline assembler, we create controls and we write libraries and dll files. Basic programmers tend to shun pointers – largely due to the onslaught of Microsoft propaganda, where direct memory access is promoted as “dangerous” and “unsafe” code. Which is rubbish – because Microsoft C# code does nothing but use pointer types in order to get the job done (talk about dumbing down the populous).

But there is one benefit of sticking with references over pointers, namely that you get to abstract the code away from the mechanism a reference points to. For instance, when compiling basic to object pascal – a reference would naturally be translates into a pointer.

But, what if you want to compile to JavaScript or Java? There is no such thing as a pointer under these languages. But if the code access memory and elements through references (in syntax), you have the benefit of adapting that to whatever target you want to compile for.

type TBufferRef = reference to memory

private sub testRef
  'our classes
  dim aRef as TBufferRef
  dim aBuffer as TBuffer

  'allocate a buffer of 1024 bytes
  aBuffer = new(TBuffer)
  aBuffer.allocate(1024)

  'get a reference to buffer memory
  set aRef = abuffer.memory

  'fill memory with $FF
  do
    aRef.setByte $FF
    aref.next
  loop until aref.eof
end sub

The above code would be easy to write utility classes for that targets native code, and would also require little work to run under javascript. The object pascal ByteRage library provides buffer code designed exactly to deal with memory and file IO in an object oriented way.

In other words, if someone follows the basic language rules – they can safely compile to both native and managed code and enjoy the benefit of pointers where available. With no change in the original source code.

I am very excited about this project — I feel the spirit of Smart Mobile Studio is going to do great things for object pascal in the near future; and indeed, other languages as well.

Search and replace dialog

Working as hard as I can to finish off the missing pieces of the IDE. Since I want the system to be small, compact and fast – I have opted to ignore the temptation of throwing X number of Delphi only components at it. I keep reminding myself that we will be porting this to Lazarus and FreePascal in a matter of months.

Non modal search dialog galore

Non modal search dialog galore

The search and replace functionality is built into SynEdit and it was just a matter of enabling it. The form design is heavily inspired by Smart Mobile Studio (in fact, more or less the same) since I feel that works well. I will however look into adding a more “modern Delphi” like search dialog – which is basically just a panel at the bottom of the editor. Perhaps I’m getting old, I seem to like the “solid and trustworthy” option as opposed to buckets of bling and fancy auto-complete-everything that kids seem to love. There is a subtle difference (ahem) between slapping something together and real craftsmanship – and I feel that RAD sometimes borders on what can be considered as such.

Styles and themes

If you are worried that I will hardcode some Delphi theme onto the IDE, I think you can relax about that. While I enjoy the “Smokey Quartz Kamri” theme, there is a bug in XE6 which for some utterly ass-hat reason turns pop-up menus into Asian menus. All the other pop-up menus work as they should, both with and without a theme so I chalk that one up to yet another bug in Delphi. Delphi XE7 is so riddled with bugs that I simply wont buy it (nor will my company which ultimately asks me what to buy).

Parsing technology

This is something that has been on my mind a lot recently. I really do enjoy writing parsers, but I must admit that since I’m going at this alone now (with the exception of Glenn which will do the port to Lazarus) there is not enough time to write a new revolution in computer history. The revolution is Smart Mobile Studio, so it’s already taking place – and it demands my spare time and attention.

As such, I have to cheat a bit. Which means making use of already existing parsers. We have used DWScript to great success with Smart Mobile Studio, which resulted in the Smart Pascal dialect. But there are alternatives out there. One of them is the Castalia parser, which is extremely fast and very puritan Delphi (so no anonymous procedures or any of the groundbreaking changes that you find in Smart Mobile Studio).

Besides these two there is PasParse, which is a relatively unknown hero in the Delphi community. It was originally written in C# as a library for code analysis, but ended up being ported to object pascal. The project has been left un maintained for a few years now, but it’s perfectly capable of parsing object pascal code all the way to the point where generics was introduced.

Generics

Personally I find generics boring. I use very little generics in my code with exception of typed object lists, a few dictionaries and basically stuff you can find in a good code library which pre-dates Delphi generics. I think the road our team took with Smart Pascal is much more interesting, and even more “pascal” than Delphi has become.

For instance, why use generics for dictionaries? It should have been array that were extended by this. Something like:

Type

TPair = Record
  Name: String;
  Value: Variant;
  constructor create(aName:String;aValue:Variant);
End;

var
FValue: Variant;
FDict: dictionary of TPair using 'name';

FDict.add(TPair.Create('test',1200));
FValue:=FDict.getValue('test');

In this type of syntax the word Array and Dictionary both allocate an array, but the dictionary keyword informs the compiler that it will in fact represent a lookup table using a field-name as the primary key.

I realize ofcourse that this is only a fraction of what generics is about, but from what I see of source-code out there, it is extremely rare that people go any deeper than typed lists, dictionaries and those features who are immediatly beneficial. The other group of people jump straight into the Spring 4D framework where 90% of the code is pure abstracted, de-coupled, generic code.

Rolling my own

I am actually thinking of using the IDE for a my basic compiler first. I know this sounds like anathema, but being able to compile an advanced form of visual basic to (drumroll) high-speed freepascal code, would no doubt turn some heads. And I need customers and investors to get something new.

Well, enough rant for today — just throwing some ideas around 🙂

First commit of QTX Pascal

I am happy to report that the first commit of QTX to SVN was done today. Which means more people will work on the project (still closed source) with me.

Once the IDE is finished, we will begin porting it to freepascal and Lazarus. So QTX will run on both Linux, Windows and OS X.

But now, I have to invest a time-frame for C# and Smart Mobile Studio, so QTX wont be updated properly until after XMAS.

But yeah, it’s getting there!

 

Battle of marathon

It’s been quite the coding marathon this weekend. Since I set a deadline for QTX today (sunday) this means I have to sort out dependencies (read: get rid of as many dependencies as possible), clean up the code a bit — and make it all ready to be committed to SVN.

Battle battle of marathon

Battle of marathon

I also got a nice email from Aaron Kaufman at Santa Monica Studio’s requesting a bit more information about QTX. I really hope we are allowed to use some GOW graphics. It doesn’t take much to spice up an otherwise boring application — and we must remember that QTX primarily aims at teaching teenagers how to program – but also to make development easier for advanced users. Either way, a cool loading picture is essential. At least for getting kids attention.

A little drop of poison

Also, time is now of the essence for me. I have roughly 14 days left until I start a new job, and I spend my days walking and doing physio therapy (I damaged 3 vertebrae). The rest is divided between my girlfriend, children, Visual Studio and C#.

So yeah, I had to install Visual Studio today and wrote my first ever program using C# in ages. It’s been at least 2 years since I played around with it, and the result was this: https://code.google.com/p/pixelrage/source/browse/trunk/pxlrage.cs

I dont know if I will ever get used to the C# event handling syntax, something about this that just doesnt stick:

  private void Form1_Load(object sender, EventArgs e)
  {
    /* Attach event handler to click delegate */
    this.Click += new System.EventHandler(handleFormClick);
  }

  private void handleFormClick(object sender, EventArgs e)
  {
    MessageBox.Show("Hello world");
  }

I mean, Smart Pascal makes a lot more sense once you get used to anonymous procedures. The above could be simplified into nothing more than:

procedure form1_load()
begin
  self.onClick:=procedure ()
    begin
      showmessage('Hello world');
    end;
end;

But no use in complaining, learning yet another language wont be hard, and I’ve used C# before. Although I must confess I prefer Mono over Visual Studio, but that’s me. Visual Studio is so bloated and huge – weighing in at around 4 gigabyte (a full DVD). Compare that to monoDevelop which is a 400 megabyte download.

QTX myth, loading picture and figurehead

Athena

Athena

While there is no official (in the true sense of the word) symbol for object pascal, Embarcadero Delphi has shipped with the traditional and stoic picture of Athena, goddess of (believe it or not) war.

This goes back to the Borland days, with the default icon for Delphi applications was, as is it now, a picture of the Delphian temple.

While the background for this choice has been debated to exhaustion in the past, why Borland decided to go with Delphi (meaning: navel of the world, the greek city states center of Dionysus worship, a pre-cursor to christ) is ultimately a thing of the past.

New wine for a new pascal

Since I have the great honor of being the grandfather (as my colleagues call it) of both Smart Mobile Studio and Quartex Pascal I figured it was time for a change.

Athena appears stoic, impotent and compared to other frameworks and languages – somewhat old fashioned and a throwback to the 70’s (read: old university idealism). Which would be roughly around the time the authors of Delphi and Turbo – lead by Anders Hejlsberg, had their exams.

Well, that was then. Athena has no doubt served us well, but I feel a more masculine motivating force is required. I have therefore been in contact with Sony Entertainment, requesting that we are allowed to use Kratos, the fear of olympus as our loading picture.

Kratos as a deity simply means “Power”. Son of Pallas and Styx, his siblings include Nike (victory), Bia (force) and and Zelus (self motivated). He ultimately represents human tenacity, will and instincts for survival. Which is feared even by the gods.

Kratos, a deity meaning "power" and "will"

Kratos, a deity meaning “power” and “will”

The background for this choice is quite simple:

  • He fights for Sparta, but will turn on his generals if betrayed, which fits well into the whole object pascal legend and symbolism
  • He fears no obstacle, which is a mentality you need as a professional programmer
  • In later popular culture (as opposed to the classic mythologies) he symbolizes anger at the custodians, which probably fits every object pascal developer on the planet considering how Borland left it’s user-base for dead.
  • He is a figure representing “activity”. He does not wait for others to save him, but takes matters into his own hands. This suits me just fine, because neither myself or my colleagues waited for Embarcadero or the FreePascal maintainers to “save” us from a a decline in job offerings. We took matters into our own hands and created a new market ourselves.
  • He get’s the job done. As he did when he bound and crucified Prometheus to the cross of Zeus in the Caucasus mountains.

A second alternative to Kratos is of-course the very god he (in Sony’s version of the myths) hunted down and killed, namely ARES. Where Athena represents (in the ancient myths) the psychological aspects of warfare, Ares represents the vessel of warfare – the instrument of divine justice if you will.

Ares, god of war

Ares, god of war

Kratos is no doubt my personal favorite since he resonates with Norwegian myth and folk-lore, but Ares or perhaps Thor (I am Norwegian after all) feels more akin to the mythology all Norwegians learn about as kids.

Thor may be a better option perhaps; I live 5 minutes from where the old viking kings of ancient times is buried (considered sacred land to some even today), so this part of our shoreline is riddled with myth. Those of us that live here cannot but become fascinated with history, mythology and our ancient legacy (albeit a bloody one).

But all good software productions should have a symbology, be it Delphi, Lazarus (a mummy? It is actually an Egytian word: [e]l-azar[us], meaning: Osiris), the Roman eagle (Aptana) or something else. So why not pick a spartan symbol with more meaning than the stoic, impotent and abstract (Athena was born from Zeus’s head, her name means “born of the mind”) Athena of ancient times?

Well, let’s see what the future brings. Words are cheap, action is what counts. I hope Sony allows us to use some graphics — or Thor it is. He might be rough and need a shave, but he is faithful until death and never leaves anyone behind.

So let it be written, so let it be done — brujah!

Multiple open projects in the IDE

Being able to edit and compile multiple projects at the same time is something we take for granted. The Delphi IDE has supported this for ages, I think it dates all the way back to Delphi 4 or something (perhaps even earlier). Sadly I was unable to add this feature to Smart Mobile Studio, which is still lacking this option, but dont be surprised if you suddenly see it emerge in SMS quite soon 😉

So why did I add this in QTX and not SMS? Well, one of the benefits of writing an IDE from scratch “second time around” is that I get to include all the stuff that I forgot last time. So when I sat down to write QTX I took several key features into consideration right from the start. Features which is the result of having done this a couple of times now (read: experience).

Multiple open projects

Multiple open projects, check out the same name no-conflict handling

This knowledge will be re-invested in Smart Mobile Studio, which is to be considered a sister-product to QTX; A bit like C++ builder is to Delphi.

Dealing with multiple projects

The key trick is to never (in the code) use string-names as a means of checking or finding an element. Always make sure your project items, files and whatnot have a unique identifier (a GUID is perfect) that you can work with. This makes it so much easier when dealing with files, open tabs, frames or whatever technology you use in your IDE.

So if you have a function called getOpenTabFor(aItemId:String;out aTab:TTabPage):Boolean;  then make sure that “aItemID” string is a GUID and not the title or name of an element/file. With that under wraps adding the rest is fairly easy.

Either way, the IDE now supports:

  • Multiple open projects
  • Projects can have the same name, but not the same file (e.g “no duplicates”)
  • When you double-click a project item in the project-explorer, the project which the item belongs to is automatically set as the active-project
  • When you close a project, only the active project is closed
  • Use “close all” to close all open projects
  • Use compile all to compile all projects in sequence (like Delphi and Lazarus)

Also added the “shortcut combo-box” above the project explorer treeview, when you have many units in a project this little drop-down list is a life saver 🙂

Also added the missing “save all”, which basically enumerates through all projects, asking if any changes has occured – and enables/disables the action accordingly. Fast, lean and elegant!

QTX on hold until after XMAS

Since I am starting a new job in december, and also since I have to dedicate some time for Smart Mobile Studio, QTX will be placed on hold starting 16’th (next sunday).

But despite all the hardship of having 2 dislocated disc’s in my back, 3 kids to take care of, and an ex-employer who is a raving, stuck-up, self centered, egomaniac nightmare — I should have most things under wraps for LDEF.

QTX is taking shape

QTX is taking shape

I must say it’s going to be a blast to compile pascal code with the newly open-sourced BlitzBasic compiler. We have to remember that BlitzBasic is hand-crafted machine code in combination with C, so it’s extremely fast. It also means we can add XBOX and Playstation to the list of supported platforms, which should open a few eyes. Pascal being focus here, being able to draw and direct the power of other technologies.

BlitzBasic packs a serious punch and is a serious tool for game developers

BlitzBasic packs a serious punch and is a serious tool for game developers

Having said that, there is quite the road ahead before we reach that goal. As it is now you can compile with Freepascal to your heart’s content, or the Delphi compiler, or the Smart Mobile compiler for that matter. But no RTL will be provided for the Smart Mobile Studio compiler – because that would be self-defeating. Smart Mobile Studio is an excellent project (if I do say so myself) and QTX is not and never will be a contender.

So for those of you who are waiting to use QTX as a free-road to SMS, that will never happen. Just so we are clear straight away regarding the use of SMS technology with QTX.

 

Pair matching

Added pair matching and various “helper” tidbits to the base editor class, with a matching preferences tab. I must admit that writing get/set procedures for so many preferences items is quite boring 🙂 But it makes for a nice editor where the user can change as much as possible to personal preferences.

Pair Matching in order

Pair Matching in order

On with the show

Work is progressing nicely, with more or less all optional (user definable) UI selections in place. When this is finally under wraps the real fun begins – namely to turn the present ini file system for defining language composition, into an editable XML based system.

Meaning, you will be able to:

  • Define a language
  • Define a project type
  • Define a project item type
  • Define highlighter and editor type for language
  • Define compiler and/or switches for both project type and item types

Now comes the real challenge, namely to abstract the compiler. Presently DWScript is the engine used by the IDE, but we will have to push that out into a plugin format (DLL files). That means that the plugin will be responsible for parsing and tokenizing a source-file, and then return LDEF data back to the IDE.

The aim is to ship the IDE with support for object pascal (FPC compiler) and Smart Basic, which is my take on visual basic on steroids. Since BlitzBasic has gone open-source lately, that will probably be the back-end compiler right there. Which will produce some insanely fast, no dependency, machine code punching executables (!)

Visually design your build-chain!

Imagine a special form where you can design the road code takes from source, to final executable.

So you drag “pascal” in first, then connect that to “basic”, and finally you connect “assembler” to basic.

What will happen then? Well, the IDE will expect pascal as the input source. It will then compile that into LDEF bytecodes.

Since Pascal is connected to Basic, it will send the LDEF code to the back codegen, which takes the LDEF code produced by the pascal code-gen, and then uses it’s basic compiler and turns that into machine code.

If you had connected another step, like say, back to pascal after Basic, then yes — it would then convert the basic LDEF code back into Pascal – before shipping the LDEF to the final codegen – which is connected to a compiler (FPC, BlitzBasic, whatever you want).

This is possible as long as there is a plugin for the IDE which supports LDEF. You can mix and match languages, output format (as long as there is a codegen registered for that output format)..

Pretty cool? I think so!

Not there quite yet — but knowing where to go is half the journey as they say 😉

Finished preferences, sort of

Phew. It’s been quite a week. Not much time for coding, but at least I managed to squeeze a day and finished off the preferences dialog.

First preferences tab

First preferences tab

And ofcourse more

Second preferences tab

Second preferences tab

And the band keeps playing

Loggin in place

Loggin in place

The paths tab is done, but I am not yet sure if I should include packages together with the search-paths. QTX is very different from Delphi and SMS, a package is more or less mounted into an internal table of “file sources”. When you right-click a unit name and select “open file at cursor” the IDE has a pretty good idea what file that is, due to the internal look-up table. So as far as the IDE is concerned, there is no difference between a package and a folder on disk. It will enumerate and chew through the filenames via the file-source API and care little about where files come from.

The benefit of this is, naturally, that packages dont require any esoteric format. In my case I have opted for ordinary .zip files which contains a few special files. So the IDE know what is a package when it deals with them, but the editor(s) dont really care (and they dont have to care). They just request files and deal with the data given to them.