[PATCH 18/25] write documentation for (system foreign declarative)

2016-07-18 Thread KAction
From: Dmitry Bogatov 

Document '' record type and 'define-foreign-type' procedure.
---
 doc/ref/api-foreign.texi | 150 ++-
 1 file changed, 147 insertions(+), 3 deletions(-)

diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi
index c2c49ec..605dbed 100644
--- a/doc/ref/api-foreign.texi
+++ b/doc/ref/api-foreign.texi
@@ -26,6 +26,7 @@ procedures.
 * Modules and Extensions::  Loading C extensions into modules.
 * Foreign Pointers::Accessing global variables.
 * Dynamic FFI:: Calling arbitrary C functions.
+* Declarative dynamic FFI:: Declarative macros for calling C functions
 @end menu
 
 
@@ -439,10 +440,10 @@ section takes up the problem of accessing C values from 
Scheme, and the
 next discusses C functions.
 
 @menu
-* Foreign Types::  Expressing C types in Scheme.
-* Foreign Variables::  Pointers to C symbols.
+* Foreign Types::   Expressing C types in Scheme.
+* Foreign Variables::   Pointers to C symbols.
 * Void Pointers and Byte Access::  Pointers into the ether.
-* Foreign Structs::Packing and unpacking structs.
+* Foreign Structs:: Packing and unpacking structs.
 @end menu
 
 @node Foreign Types
@@ -980,6 +981,149 @@ on a few exotic architectures.  Thus, user code may need 
to check
 many architectures, including (as of libffi 3.0.9) x86, ia64, SPARC,
 PowerPC, ARM, and MIPS, to name a few.
 
+@node Declarative dynamic FFI
+@subsection Declarative dynamic FFI
+
+Dynamic foreign function interface, described in previous section is
+powerful and sufficient to bind power of almost any C library to Guile
+with only Scheme code. But it is very low-level and does not provide any
+abstractions for common function conventions. This is where module
+@code{(system foreign declarative)} comes into the game.
+
+@deftp {Record type}  name validate encode decode type
+@code{} record represents correspondence between C data
+type and some Scheme object. It contains @code{name} for purposes of
+error reporting, procedure @code{validate}, which will can be called
+with single argument and return @code{#t} if it's argument is suitable
+for passing to @code{encode} procedure, and return @code{#f} or throw if
+not.
+
+Procedure @code{encode} converts Scheme object of arbitrary complexity
+to C data type, coherent to @code{type}. @xref{Dynamic FFI} Procedure
+@code{decode} converts back from C data type to some Scheme object.
+At least one of them should be present for record be useful.
+
+Fields of @code{} record must (but not enforced)
+to obey following rules:
+
+@enumerate
+
+@item
+Every procedure @code{validate}, @code{encode} and @code{decode} are
+pure -- their result depends only on argument, and they do nothing,
+except of returning a value.
+@example
+;; for every `procedure' from 'validate', 'encode', 'decode'
+;; for every Scheme value `x'
+;; following expressions are either both throw or return same value.
+;; they can freely be replaced one with another.
+(list (procedure x)
+  (procedure x))
+(let ((value (validate x))
+ (list value value)))
+@end example
+
+@item
+If field @code{decode} is present, procedure @code{decode} accepts any
+argument with type matching @code{type} field and returns normally some
+value. If both @code{decode} and @code{encode} fields are present,
+value, returned by @code{decode} procedure, can be encoded back by
+@code{encode} procedure.
+@example
+;; For every Scheme value 'x', matching field 'type' following expression
+;; never throw and always evaluates to #t
+(equal? (encode (decode x)) x)
+@end example
+
+@item
+For every value, for which @code{validate} procedure returned @code{#t},
+@code{encode} procedure returns normally.
+@example
+;; For every Scheme value 'x' following expression never throws
+(and (false-if-exception (validate x))
+ (encode x))
+@end example
+@end enumerate
+@end deftp
+
+@deffn {Scheme Macro} define-foreign-type name  @
+[#:validate-proc=(const #t)]@
+[#:encode-proc=error]   @
+[#:decode-proc=error]   @
+[#:type='*]
+Defines @code{name} to a @code{} record with @code{name},
+fields @code{validate-proc}, @code{encode-proc}, @code{decode-proc},
+@code{type} configured with keywords arguments.
+
+Here is how one may define foreign type record, that match C integer with
+Scheme boolean
+@example
+(use-modules (system foreign)) ;; `int' is defined there
+(use-modules (system foreign declarative))
+
+(define (boolean->integer b)
+  (if b 1 0))
+(define (integer->boolean i)
+  (not (zero? i))
+
+(define-foreign-type boolean:
+  #:validate-proc boolean?
+  #:encode-proc boolean->integer
+  #:decode-proc integer->boolean
+  #:type int)
+@end example
+By convention, @code{} record's names ends with colon.
+@end deffn
+
+Module @code{(system foreign declarative)} provides such records for
+every pr

Re: [PATCH 18/25] write documentation for (system foreign declarative)

2016-07-18 Thread Amirouche Boubekki

On 2016-07-18 17:17, kact...@gnu.org wrote:

From: Dmitry Bogatov 

Document '' record type and 'define-foreign-type' 
procedure.


Can you compare this 'foreign-type' library with scheme-bytestructures 
[0]. How

can both libraries help each other? Work hand in hand?

[0] https://github.com/TaylanUB/scheme-bytestructures

Tell me if I'm wrong but it looks like you have to define validate, 
encode
and decode proc for every single structure with no helpers. It seems to 
me
that it's some kind of framework for doing validation of static typed 
procedures

which also handles automatic conversion between C land and scheme land.

Honestly this is not the kind of library I would use, I seldom do input 
validation
when the client of my program is a developer. Maybe I'm wrong but IMO 
dynamic languages

help that.

Also based on my small experience of ffi, there is not much conversion 
to do between
scheme and C and what's best is to avoid any copy which is what does 
scheme-bytestructures.


WDYT?


Thanks!


--
Amirouche ~ amz3 ~ http://www.hyperdev.fr



Re: [PATCH 18/25] write documentation for (system foreign declarative)

2016-07-18 Thread Dmitry Bogatov
[2016-07-18 21:41] Amirouche Boubekki 
>
> On 2016-07-18 17:17, kact...@gnu.org wrote:
> > From: Dmitry Bogatov 
> >
> > Document '' record type and 'define-foreign-type'
> > procedure.
>
> Can you compare this 'foreign-type' library with scheme-bytestructures
> [0]. How
> can both libraries help each other? Work hand in hand?

Seems that 'scheme-bytestructures' can be used to implement something like
`define-foreign-struct', but since it is not currently part of Guile, I, sure,
can't depend on it.

Also, 'parse-c-struct' provides similiar functionality.

> Tell me if I'm wrong but it looks like you have to define validate,
> encode and decode proc for every single structure with no
> helpers.

Not true. Sure, if your conversion is somewhat unusual, you have to
invoke `(define-foreign-type)', but if it conventional, you can use

  - define-foreign-bitmask
  (in future)
  - define-foreign-struct (did not extracted from guile-bash)
  - define-foreign-enumeration
  - define-foreign-opaque
  (last two are really trivial, just I did not needed them for xattr library)

> It seems to me that it's some kind of framework for doing validation
> of static typed procedures which also handles automatic conversion
> between C land and scheme land.  Honestly this is not the kind of
> library I would use, I seldom do input validation when the client of
> my program is a developer. Maybe I'm wrong but IMO dynamic languages
> help that.

Our opinions on validation differs. I think, that foreign function
binding, created by (system foreign declarative) should be as good, as
if written in C. By this I mean, I want to get error message out of
function itself, not from some guts of (system foreign declarative).

> Also based on my small experience of ffi, there is not much
> conversion to do between scheme and C and what's best is to avoid
> any copy which is what does scheme-bytestructures.

(system foreign declarative) provide a way to work with memory with no copy:

(with-pointer ((memory *--> 1024))
 (foreign-call memory)
  (work-with-bytevector memory))

But take a look at (ice9 xattr) (patches 21-25).

Conversion from Scheme string to `const char *' have O(n) price, but I
prefered natural interface to perfomance. But again, (system foreign
declarative) does not force such choice.

It seems to me, that I responded to every point, but feel free to
refine your question.

-- 
Accept: text/plain, text/x-diff
Accept-Language: eo,en,ru
X-Web-Site: sinsekvu.github.io



Re: [PATCH 18/25] write documentation for (system foreign declarative)

2016-07-19 Thread Taylan Ulrich Bayırlı/Kammer
Dmitry Bogatov  writes:

> [2016-07-18 21:41] Amirouche Boubekki 
>>
>> On 2016-07-18 17:17, kact...@gnu.org wrote:
>> > From: Dmitry Bogatov 
>> >
>> > Document '' record type and 'define-foreign-type'
>> > procedure.
>>
>> Can you compare this 'foreign-type' library with scheme-bytestructures [0].
>> How can both libraries help each other?  Work hand in hand?
>
> Seems that 'scheme-bytestructures' can be used to implement something like
> `define-foreign-struct', but since it is not currently part of Guile, I, sure,
> can't depend on it.
>
> Also, 'parse-c-struct' provides similiar functionality.

I was keeping an eye on this thread because it sounded like something
bytestructures could help in.  Tell me if you need cooperation; I'm the
author of bytestructures.

I'm not sure if the Guile maintainers would like to make bytestructures
a part of Guile as it stands, but I have my FSF copyright assignment
paperwork done and from my side all is fine.  John Cowan wants to make
it a SRFI for possible adoption in R7RS-large, which would have some
implications on future design and implementation choices in the project
(e.g. not making it dependent on any Guile-specific concepts) but I'll
prioritize Guile if I'm forced to make choices.

Taylan



Re: [PATCH 18/25] write documentation for (system foreign declarative)

2016-07-19 Thread Dmitry Bogatov

> > Seems that 'scheme-bytestructures' can be used to implement something like
> > `define-foreign-struct', but since it is not currently part of Guile, I, 
> > sure,
> > can't depend on it.
> >
> > Also, 'parse-c-struct' provides similiar functionality.
>
> I was keeping an eye on this thread because it sounded like something
> bytestructures could help in.  Tell me if you need cooperation; I'm the
> author of bytestructures.
>
> I'm not sure if the Guile maintainers would like to make bytestructures
> a part of Guile as it stands, but I have my FSF copyright assignment
> paperwork done and from my side all is fine.  John Cowan wants to make
> it a SRFI for possible adoption in R7RS-large, which would have some
> implications on future design and implementation choices in the project
> (e.g. not making it dependent on any Guile-specific concepts) but I'll
> prioritize Guile if I'm forced to make choices.

Glad to meet cooperation. I think we will return to this question when

 * (system foreign declarative) is incorporated into Guile

 * (system foreign declarative) will get need to support C structures
   due need to write bindings to some external library.

25 patches is already a lot for maintainers to review, and I would
prefer to not scare maintaners further.

A bit offtopic question: am I correct, that there is no way to write
bindings (purely from Guile, no C) to functions, that accept struct
arguments by value?

  struct foo { int x; double y; };
  void frob(const struct foo);

-- 
Accept: text/plain, text/x-diff
Accept-Language: eo,en,ru
X-Web-Site: sinsekvu.github.io