Skybuck Flying
6/30/2011 5:54:00 PM
Proof of concept demonstration program, showing some issues with current
programming language design/limitations and how to work around that, further
paths for investigation provided, and further syntax ideas provided.
Current program demonstration is limited to Delphi only for now, since C/C++
does not even have properties so C/C++ is more limited already.
The goal is ofcourse to make programming as easy as possible.
The solution provided below is on it's way to become easy usuable, as
mentioned further path for investigation is using a different operator to be
used as operator overloading to try and automate the passing of the base
pointer to the next indirection/record.
Perhaps
Block[ 1000 ] * Element[ 2000] = 1000;
Might work... the * operator could be overloaded (perhaps delphi has a colon
operator overloader but I don't think so)
^ This idea might work if indeed PDynamicPointers are passed to the operator
overloader, then access to base pointers and strides should be
allowed/possible and thus this code can be automated to pass base pointer
from block to element for element access.
However there is a problem... element[2000] is probably evaluated before the
multiple operator is invoked and thus it seems not possible to use the
operator * overloader unless the index/pointer calculation can be re-done
after the fact/invokation of the * operator overloader.
The ultimate goal of the * operator overloader would be to provide an
address which can then be written to be the assignment operator.
So in a way it could be possible if dynamic pointers or in this case
element stores the index that it wants to write to.
Then * operator overloader could be used to return a pointer.
Finally the user could override the pointer with a typecast as follows:
PInteger( Block[1000] * Element[2000] )^ := 1000;
So this short examination above does seem to provide a solution to mimic
this new language behaviour.
This idea above has not yet been explored/implemented in the example above,
but it's pretty interesting so I will try in a next example.
For now here is the first example/version, showing compiler/language
limitations and manual work arounds:
To be precise the language limitation is in pointers:
Pointers are in a way static, their strides are static, they depend on the
type to which the pointer points (static "typed pointers").
General programming languages need to be enhanced to prevent "dynamic
pointers".
Where their strides can be specified at runtime to allow flexibility for
multi-dimensional programming which will probably become more important in
the future as processors/transistor run into switching speed limitations and
the only way to add more speed is to increase the ammount of transistors and
chips leading to dimensionality... be it 1d or multi-d.
Some flexibility for programming solutions is then required, since these
chips will have different sizes/dimensionalities, and so do memory chips and
thus computational problems which need to be flexible solved to what the
capabilities of the systems are, thus flexible software required. Assuming
that 1 GB arrays will fit on all is bad assumption, these arrays need to be
flexible, and thus flexible pointers required.
Perhaps hardware will make things easy for as programmers by providing
simple multi dimensional to single dimension translations/mappings and vice
versa, or perhaps not, in the latter case we programmers need better
languagees to support these multi dimensional situations ;)
Even just 1D already requires this to be able to program it easy.
Think of a single core as 0D ;) (<- this era seems over)
// *** Begin of Test Program ***
program TestProgram;
{$APPTYPE CONSOLE}
{
Test dynamic pointer indexing and base passing idea
version 0.01 created on 30 june 2011 by Skybuck Flying.
Dynamic pointer type record provided below.
It consumes no memory in the final memory output.
It does use local variables/record fields to store it's base/field but these
are not stored in the memory block which is a good thing.
The pointers returned are all directly into the memory block.
Yet because they are of type PDynamicPointer it is allowed to invoke further
indirection/array index operator which is also a good thing.
In this first test I see no delphi/pascal language facility yet to
automatically
pass the calculated base pointer to the next indirection.
Thus this is done manually in code section (*).
This is were compiler help would be usefull, or a new language feature for
example
the suggested : colon operator to pass values to the next indirection/next
record
Perhaps a different existing operator could be used to mimic/implement this
behaviour
via some form of operator overloading. So further investigations could
deliver interesting results.
Which leaves the issue of having to typecast the dynamic pointer to the
final type to use...
in this example the integer type.
A further suggestion is to allow the following syntax declaration to
automate these typecasts by the compiler:
var
Element : dynamic pointer to integer;
This could automatically setup up the stride and the type so no typecasting
required.
}
uses
SysUtils;
type
PDynamicPointer = ^TDynamicPointer;
TDynamicPointer = record
private
mBase : pointer;
mStride : integer;
function PerformArrayIndexOperator( ParaIndex : integer ) :
PDynamicPointer;
// procedure PerformArrayIndexOperatorWrite( ParaIndex : integer;
ParaDynamicPointer : PDynamicPointer );
public
property Base : pointer read mBase write mBase;
constructor Create( Base : pointer; Stride : integer );
property ArrayIndexOperator[ ParaIndex : integer ] : PDynamicPointer read
PerformArrayIndexOperator; default;
end;
constructor TDynamicPointer.Create( Base : pointer; Stride : integer );
begin
mBase := Base;
mStride := Stride;
end;
function TDynamicPointer.PerformArrayIndexOperator( ParaIndex : integer ) :
PDynamicPointer;
begin
result := PDynamicPointer( longword(mBase) + longword(ParaIndex) *
longword(mStride) );
end;
(*
procedure TDynamicPointer.PerformArrayIndexOperatorWrite( ParaIndex :
integer; ParaDynamicPointer : PDynamicPointer );
begin
result := PDynamicPointer( longword(mBase) + longword(ParaIndex) *
longword(mStride) );
end;
procedure PerformArrayIndexOperatorWrite( ParaIndex : integer;
ParaDynamicPointer : PDynamicPointer );
*)
procedure Main;
var
Memory : pointer;
Block : TDynamicPointer;
Element : TDynamicPointer;
ElementCount : integer;
ElementSize : integer;
BlockCount : integer;
BlockSize : integer;
BlockIndex : integer;
ElementIndex : integer;
Check : Pinteger;
begin
ElementCount := 8000;
ElementSize := 4;
BlockCount := 2000;
BlockSize := ElementCount * ElementSize;
GetMem( Memory, BlockCount * BlockSize );
Block := TDynamicPointer.Create( Memory, BlockSize );
Element := TDynamicPointer.Create( nil, ElementSize );
// Block[ 1000 ].Element[ 2000 ] := 4;
// ^ cannot pass base pointer. (current language limitation )
// cannot assign pointer to element, perhaps operator overloading might
help.
// Element := Block[ 1000 ];
// for now we do passing the base manually:
Element.Base := Block[ 1000 ]; // (*)
// another problem we face, cannot overload the pointer to be a pointer to a
type
// so typecast needed, or we could introduce a special property but this
would be a property per type less ideal.
PInteger(Element[ 2000 ])^ := 666;
// Now let's test if the element went were it should be:
BlockIndex := 1000;
ElementIndex := 2000;
Check := Pinteger( longword(Memory) + longword(BlockIndex) *
longword(BlockSize) + longword(ElementIndex) * longword(ElementSize) );
writeln( Check^ ); // correct it displays 666.
// Conclusion:
// A General dynamic pointer type is already possible, this allows to embed
base and stride into a record
// which can then be a record to a record to a record for easy/automatic
multi dimensional support/extensibility/flexibility.
// What is needed is a little bit of compiler help to automate the above
code in a more nicely to use syntax sugar
// so that it can automaticaly pass the base as in code section (*);
// some automatic type casting would also be nice.
// which could be done last like so:
// then the stride would already be known... or at least the type be known !
;)
{
Block : dynamic pointer;
Element : dynamic pointer to integer;
}
FreeMem( Memory, BlockCount * BlockSize );
end;
begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
// *** End of Test Program ***
Bye,
Skybuck.