On Wed, Jan 9, 2013 at 12:10 AM, Igor Stasenko <siguc...@gmail.com> wrote:

> On 8 January 2013 19:38, Eliot Miranda <eliot.mira...@gmail.com> wrote:
> >
> >
> >
> > On Fri, Jan 4, 2013 at 12:37 AM, Igor Stasenko <siguc...@gmail.com>
> wrote:
> >>
> >> On 4 January 2013 08:54, Torsten Bergmann <asta...@gmx.de> wrote:
> >> > When one deploys an image one usually requires ONLY
> >> > the image - not the source or changes file. An "image locker"
> >> > code would look like this:
> >> >
> >> >   SmalltalkImage checkSourcesFileAvailability: false.
> >> >   SmalltalkImage checkChangesFileAvailability: false
> >> >
> >> > do disable acording warnings when source/changefile is removed.
> >> >
> >> > If one uses NativeBoost in such a deployment scenario, for
> >> > instance the
> >> >
> >> >   NBWin32Shell shellBrowse: 'http://www.google.de'
> >> >
> >> > functionality the internal code (due to missing source) now
> >> > looks like this
> >> >
> >> >   shellExecute: t1 file: t2 parameters: t3 directory: t4 show: t5
> >> >         <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'>
> >> >         ^ self nbCall: #(#HINSTANCE #ShellExecuteA #(0 #, #LPCTSTR
> >> > #lpOperation #, #LPCTSTR #lpFile #, #LPCTSTR #lpParameters #, #LPCTSTR
> >> > #lpDirectory #, #INT #nShowCmd ) ) module: 'Shell32.dll'
> >> >
> >> > Hence the t1 ... t5 parameters.
> >> >
> >> > NativeBoost is in this situation not able to match the
> >> > FFI parameters and throws an error "Could not find accessor for
> variable
> >> > ..."
> >> >
> >> > Try yourself without a changes and source file. This makes
> >> > NativeBoost not very deployment friendly and unusable in
> >> > such a "minimal deployment" scenario ...
> >> >
> >> > Any comments?
> >> >
> >>
> >> yes it needs sources (indirectly) to bind method's argument names
> >> during code generation.
> >> To avoid that, i can imagine that one must modify a compiler to detect
> >> if compiled method
> >> primitive requires arg names, and store them in method properties.
> >> Like that later code generator can use them without need to access the
> >> source code.
> >
> >
> > Indeed.  If a pragma were used then the whole thing could look a lot
> nicer,
> > not be dependent on source, and include support for an error code.  e.g.
> >
> > shellExecute: lpOperation file: lpFile parameters: lpParameters
> directory:
> > lpDirectory show: nShowCmd
> >
> >         <nbCall: #(#HINSTANCE #ShellExecuteA #(0 #, #LPCTSTR
> #lpOperation #,
> > #LPCTSTR #lpFile #, #LPCTSTR #lpParameters #, #LPCTSTR #lpDirectory #,
> #INT
> > #nShowCmd ) )
> >           module: 'Shell32.dll'
> >           errorCode: ec>
> >
> >         ^self nbCallFailedWith: ec
> >
> > It's pretty trivial to add such pragma compilers to the compiler.  There
> is
> > an example for the FFI.  It also frees one to use a nicer syntax, e.g.
> >
> > shellExecute: lpOperation file: lpFile parameters: lpParameters
> directory:
> > lpDirectory show: nShowCmd
> >         <nbCall: 'HINSTANCE ShellExecuteA(0, LPCTSTR lpOperation, LPCTSTR
> > lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd)'
> >           module: 'Shell32.dll'
> >           errorCode: ec>
> >
> >         ^self nbCallFailedWith: ec
> >
>
> i do not see how encoding function signature in pragma could help with
> binding argument names.
>

Because your pragma processing code can add additional state, i.e. the map
form input argument order to call argument order.


> Yes, you need to get some control at compile time to be able to encode
> method arg names somewhere in method properties for later use.. but
> not at cost of moving everything into pragma.
>

What's this "cost"?  The call info has to live somewhere.


>
> And 'nice' syntax is actually already there .. nothing prevents you
> from using strings for function signature, e.g.
>
> self nbCall: 'int foo()'
> equivalent to
> self nbCall: #(int foo() )
>
> (i don't know why Torsten gave code in such form, that could leave an
> impression that syntax is horrible ;)
>
> And besides, how you suppose to "pragmatize" following:
>
> storeDouble: aDouble at: address
>         " This method stores a double floating point value at given memory
> address.
>         an address can be an instance of NBExternalAddress, or
>         simple ByteArray with at least 8 bytes long, which will hold a
> 64bit
> floating-point value"
>
>         <primitive: 'primitiveNativeCall' module: 'NativeBoostPlugin'
> error: errorCode>
>
>         ^ self nbCallout
>                  options: #(
>                 - optCoerceNilToNull
>                 + optAllowByteArraysPtr
>                 + optAllowExternalAddressPtr
>                 );
>                 function: #( void (void * address, double aDouble) )
>                 emit: [:gen |  | asm |
>                         asm := gen asm.
>
>                         "Here , we expecting that an address value is on
> top of the stack"
>                         asm
>                                 pop: EDX;  "load an address value into EDX
> register by popping it
> from a stack"
>
>                                 "now copy the floating point value (which
> is 8-bytes long) to the
> given address"
>                                 mov: ESP ptr to: EAX;
>                                 mov: EAX to: EDX ptr;  " store first 32bit
> part of 64bit double value"
>
>                                 mov: ESP ptr + 4 to: EAX;
>                                 mov: EAX to: EDX ptr + 4.  " store second
> 32bit part of 64bit double value"
>
>                 ]
>

Just wrap the assembler up in a string.  But this low level shouldn't be
necessary.  If you went the compile-time route then you'd analyse the call
according to the platform's ABI and figure out the assembler automatically.
 This is the architecture I was hoping yopu'd implement.  If the
compilation step is left until the first call then the signatire becomes
platform-independent.

For a clunkier approach see my callback implementation where you build up a
library of transformers indexed by signature.  The library contains
different versions for each platform.  If you applied this simple idea to
the above you'd have some pragma somewhere which said "on x86 with
signature #( void (void * address, double aDouble) ) output this
marshalling code: #(pop: EDX "load an...") etc.  And then the call site
would just supply the signature.  You'd get to share the marshalling code
between functions having the same signatures and you'd have a level of
platform-independence.

-- 
best,
Eliot

Reply via email to