Mailing List Archive

Re: xsubpp2a1: XSUB + C structures, alpha release 1
Paul Marquess writes:
> I've been hacking xsubpp on my own long enough so I thought it was
> about time I threw it over the wall. Things are still a bit rough
> around the edges, parts just don't work yet, parts will probably change
> or be deleted, but there should be enough working for you all to play
> with (I hope).
>
> Although I would consider this to be more of a prototype, I have taken
> the liberty of calling this xsubpp 2.000 alpha 1. As with any alpha
> code, the interface and functionality defined here will very likely
> change, so don't go writing any mission critical code with it just
> yet.
>

I had only a cursory look over it, but I did not understand how one
would approach run-time polymorphism with this guy.

I have two cases in mind: SV and OP.

A flag field in an SV determines the actual type of the pointer that
is another field.

A flag type in OP determinies the actual type of OP itself.

I'm completely blocked now.

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Paul Marquess writes:
>
> Ilya wrote:
> >
> > I had only a cursory look over it, but I did not understand how one
> > would approach run-time polymorphism with this guy.
> >
> > I have two cases in mind: SV and OP.
> >
> > A flag field in an SV determines the actual type of the pointer that
> > is another field.
> >
> > A flag type in OP determinies the actual type of OP itself.
> >
> > I'm completely blocked now.
>
>
> It *is* possible to do this kind of thing as xsubpp 2.x currently
> stands. Unfortunately it is rather cumbersome. Basically you would have
> to write custom FETCH and STORE methods for each element in all of the
> structs.
>
> What I could do instead is add a keyword to allow casting for
> individual elements of a structure.
>
> Say we have 2 structures
>
> struct base
> { int type ;
> int alpha ;
> } ;
>
> struct base1
> { int type ;
> int beta ;
> }
>
> A unified interface to both structures could be written like this (once
> I add the CAST keyword and logic).
>
> TYPE HASH
>
> struct base ;
> int type ;
> int alpha ;
> int beta ;
> CAST: beta (struct base1 *)
>
>
> I've just had a quick look at the xsubpp source and at first glance
> it seems quite easy to add the necessary logic.
>
> I'll think about it some more and if there isn't something drastic I've
> overlooked, I'll add it in.
>
> Paul
>

What looks missing is
CASTIF: (type & MASK) == BLAH

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
This whole thing remind me strongly of Pascal variants (or whatever they
are called) that look something (transliterated into C) like this:


struct c {
case int c {
1: int i,j;
2: char i,j;
3: long a,f;
}
}

You get the same effect as a union if there isn't any actual case variable.

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Paul Marquess writes:
> > > A unified interface to both structures could be written like this (once
> > > I add the CAST keyword and logic).
> > >
> > > TYPE HASH
> > >
> > > struct base ;
> > > int type ;
> > > int alpha ;
> > > int beta ;
> > > CAST: beta (struct base1 *)
> > >
> > >
> > > I've just had a quick look at the xsubpp source and at first glance
> > > it seems quite easy to add the necessary logic.
> > >
> > > I'll think about it some more and if there isn't something drastic I've
> > > overlooked, I'll add it in.
> > >
> > > Paul
> > >
> >
> > What looks missing is
> > CASTIF: (type & MASK) == BLAH
>
> This is starting to get very like the CASE: functionality that I fixed
> in xsubpp a while back. I wonder if it would be better to add something
> similar to the structure code? Might be more general purpose than just
> adding CAST logic and it would be consistant with what is already
> there.
>

I do not remember what CASE does, but another candidate for plagiarism
is ALIAS.

ALIASBY $self->type & MASK
ALIAS 1=BINOP 2=UNOP ...

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
>
> Paul Marquess writes:
> > > > A unified interface to both structures could be written like this (once
> > > > I add the CAST keyword and logic).
> > > >
> > > > TYPE HASH
> > > >
> > > > struct base ;
> > > > int type ;
> > > > int alpha ;
> > > > int beta ;
> > > > CAST: beta (struct base1 *)
> > > >
> > > >
> > > > I've just had a quick look at the xsubpp source and at first glance
> > > > it seems quite easy to add the necessary logic.
> > > >
> > > > I'll think about it some more and if there isn't something drastic I've
> > > > overlooked, I'll add it in.
> > > >
> > > > Paul
> > > >
> > >
> > > What looks missing is
> > > CASTIF: (type & MASK) == BLAH
> >
> > This is starting to get very like the CASE: functionality that I fixed
> > in xsubpp a while back. I wonder if it would be better to add something
> > similar to the structure code? Might be more general purpose than just
> > adding CAST logic and it would be consistant with what is already
> > there.
> >
>
> I do not remember what CASE does, but another candidate for plagiarism
> is ALIAS.
>
> ALIASBY $self->type & MASK
> ALIAS 1=BINOP 2=UNOP ...

Hmmm, not sure how that would work.

Paul
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
I tried my own ("real life") extension, and now it compiles and runs
(not sure that it does it correct, though). I needed some additions to
the posted code.

Target of the patch below is to make it possible to patch a portion of
.h file into .xs file without any change. I succeeded in my particular
case. For this I needed a new TYPEDEF section in .xs, and needed to
allow trailing comments in descriptions of structures.

Here is a piece of code _from_ my .xs:

============================================================

TYPEDEFS

typedef U32 ULONG;
typedef unsigned short USHORT;
typedef unsigned char UCHAR;
typedef I8 CHAR;
typedef void VOID;
typedef U32 UINT;

TYPE HASH

typedef struct qsGrec_s {
ULONG cThrds; /* number of threads in use */
ULONG Reserved1;
ULONG Reserved2;
}qsGrec_t;


/**********************************/
/* Thread record */
/**********************************/
typedef struct qsTrec_s {
ULONG RecType; /* Record Type */
/* Thread rectype = 100 */
USHORT tid; /* thread ID */
USHORT slot; /* "unique" thread slot number */
ULONG sleepid; /* sleep id thread is sleeping on */
ULONG priority; /* thread priority */
ULONG systime; /* thread system time */
ULONG usertime; /* thread user time */
UCHAR state; /* thread state */
CHAR pad1;
} qsTrec_t;


============================================================

What I'm missing a lot is FIRSTKEY and friends, to make examination of
structures from debugger simpler.

Ilya

PS A patch below corrects a couple of errors in the code as well, and
makes 3 or 4 cosmetic changes to make editing with emacs simpler.

*** F:/ckermit/get/XSUBPP-2.000a1/xsubpp Mon Jul 24 05:08:10 1995
--- xsubpp Sat Sep 30 02:41:14 1995
***************
*** 40,45 ****
--- 40,59 ----
$_[0] =~ s/^\s+|\s+$//go ;
}

+ sub TrimTrailingComment
+ {
+ $_[0] =~ s,/\*([^*]|\*[^/])*\*+/\s*$,,go ; # hairy enough?
+ }
+
+ sub SubstTypedefs {
+ my $first, $rest;
+ while (1) {
+ ($first, $rest) = ( $_[0] =~ /^([\w_]+)(.*)$/ );
+ last unless defined $first and defined $Typedefs{$first};
+ $_[0] = $Typedefs{$first} . $rest;
+ }
+ }
+
sub TidyType
{
local ($_) = @_ ;
***************
*** 54,62 ****
--- 68,82 ----
# change multiple whitespace into a single space
s/\s+/ /g ;

+ # trim trailing comment
+ TrimTrailingComment($_) ;
+
# trim leading & trailing whitespace
TrimWhitespace($_) ;

+ # Process typedefs
+ SubstTypedefs($_) ;
+
$_ ;
}

***************
*** 147,153 ****
# Return: the matched keyword if found, otherwise 0
sub check_keyword {
$_ = shift(@line) while !/\S/ && @line;
! s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
}


--- 167,173 ----
# Return: the matched keyword if found, otherwise 0
sub check_keyword {
$_ = shift(@line) while !/\S/ && @line;
! s/^(\s*)($_[0])\s*:\s*(?:\#.*)?/$1/s && $2;
}


***************
*** 272,278 ****
print <<"EOF" ;
/*
* This file was generated automatically by xsubpp version $XSUBPP_version from the
! * contents of $filename. Don't edit this file, edit $filename instead.
*
* ANY CHANGES MADE HERE WILL BE LOST!
*
--- 292,298 ----
print <<"EOF" ;
/*
* This file was generated automatically by xsubpp version $XSUBPP_version from the
! * contents of $filename. Do not edit this file, edit $filename instead.
*
* ANY CHANGES MADE HERE WILL BE LOST!
*
***************
*** 333,338 ****
--- 353,401 ----
1;
}

+ sub TrimLeadingComments { # Delete whole comment lines from beg of @line
+ my $start;
+ while (@line) {
+ $start = shift @line;
+ TrimTrailingComment($start);
+ if ($start !~ /^\s*$/) {
+ unshift @line, $start;
+ last;
+ }
+ }
+ }
+
+ %Typedefs = ();
+
+ sub ParseTypedefs {
+ my ($copy, $source, $dest, @words);
+ for $line (@_) {
+ $copy = $line;
+
+ # remove any trailing ;
+ $line =~ s/\s*;\s*$// ;
+
+ # trim whitespace
+ TrimWhitespace($line);
+
+ #
+ blurt("Error: invalid typedef in line '$copy'"), next
+ unless ($line =~ s/^\s*typedef\s+//);
+ @words = split ' ', $line;
+
+ # We consider only the case when the source is the last word on the line
+ $source = pop @words;
+ $dest = join ' ', @words;
+
+ # move leading stars from source to destination
+ $dest .= $1 if $source =~ s/^(\*+)//;
+ blurt("Error: invalid source '$source' in line '$copy'"), next
+ unless ($source =~ /^[\w_]+$/);
+ $Typedefs{$source} = $dest;
+ }
+ }
+
+
$Section = 'XSUB' ;

PARAGRAPH:
***************
*** 358,363 ****
--- 421,427 ----
undef(%arg_list) ;


+ TrimLeadingComments;
$_ = shift(@line);
if (check_keyword("BOOT")) {
&check_cpp;
***************
*** 369,375 ****
my($ret_type) = TidyType($_);

# Check for change of section
! if ($ret_type =~ s/^(TYPE|XSUB|VAR)\s*//) {
$Section = $1 ;

if ($Section eq 'TYPE') {
--- 433,439 ----
my($ret_type) = TidyType($_);

# Check for change of section
! if ($ret_type =~ s/^(TYPE(DEFS)?|XSUB|VAR)\s*//) {
$Section = $1 ;

if ($Section eq 'TYPE') {
***************
*** 402,407 ****
--- 466,476 ----
next PARAGRAPH ;
}

+ if ($Section eq 'TYPEDEFS') {
+ ParseTypedefs($ret_type, @line) ;
+ next PARAGRAPH ;
+ }
+
# Default section is XSUB

# a function definition needs at least 2 lines
***************
*** 742,749 ****
$subexpr =~ s/ntype/subtype/g;
$subexpr =~ s/\$arg/ST(ix_$var)/g;
$subexpr =~ s/\n\t/\n\t\t/g;
! $subexpr =~ s/is not of (.*")/[arg %d] is not of $1, ix_$var + 1/g;
! $subexpr =~ s/\$var/${var}[ix_$var - $argoff]/;
$expr =~ s/DO_ARRAY_ELEM/$subexpr/;
}
if (defined($defaults{$var})) {
--- 811,818 ----
$subexpr =~ s/ntype/subtype/g;
$subexpr =~ s/\$arg/ST(ix_$var)/g;
$subexpr =~ s/\n\t/\n\t\t/g;
! $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
! $subexpr =~ s/\$var/$ {var}[ix_$var - $argoff]/;
$expr =~ s/DO_ARRAY_ELEM/$subexpr/;
}
if (defined($defaults{$var})) {
***************
*** 1406,1411 ****
--- 1475,1483 ----
my ($array_size) ;
my ($got_array) = 0 ;

+ # remove trailing comment
+ TrimTrailingComment($line) ;
+
# remove leading & trailing whitespace
TrimWhitespace($line) ;

***************
*** 1455,1469 ****
my (%tailor) ;
my (%elements) ;
my (%methods) ;

blurt ("Error: No structure definition for $struct_name"), return
unless @line ;

# remove any trailing {
! $struct_name =~ s/\s*{\s*$// ;

# trim whitespace
TrimWhitespace($struct_name) ;
$struct_type = $struct_name ;

# fatal error if no structure name present
--- 1527,1543 ----
my (%tailor) ;
my (%elements) ;
my (%methods) ;
+ my $typedefed;

blurt ("Error: No structure definition for $struct_name"), return
unless @line ;

# remove any trailing {
! $struct_name =~ s/\s*\{\s*$// ;

# trim whitespace
TrimWhitespace($struct_name) ;
+ $typedefed = 1 if $struct_name =~ s/^\s*(typedef)\s+// ;
$struct_type = $struct_name ;

# fatal error if no structure name present
***************
*** 1491,1498 ****

$_ = shift(@line) ;

! s/^\s*{\s*// ;
! s/\s*}\s*;?\s*$// ;
next if /^\s*$/ ;

#my ($decl, $init) = split(/\s*=\s*/, $_, 2) ;
--- 1565,1583 ----

$_ = shift(@line) ;

! s/^\s*\{\s*// ;
!
! TrimTrailingComment($_);
!
! s/\s*\}\s*;?\s*$// ;
!
! if ($typedefed
! && s/\s*\}\s*([\w_]+[\s,]*)+\s*;?\s*$//) { # process typedefs
! foreach $word (split /[,\s]+/, $1) {
! $Typedefs{$word} = "struct $struct_name";
! }
! }
!
next if /^\s*$/ ;

#my ($decl, $init) = split(/\s*=\s*/, $_, 2) ;
***************
*** 1584,1590 ****
#
# ST(0) = Ref2Tied($t_HASH, "${Package}::$struct_name",
# sizeof($struct_type), 1,
# ) ;
EOF
foreach $element (@struct) {
--- 1669,1675 ----
#
# ST(0) = Ref2Tied($t_HASH, "${Package}::$struct_name",
# sizeof($struct_type), 1,
# ) ;
EOF
foreach $element (@struct) {
***************
*** 1829,1835 ****
#
# ST(0) = Ref2Tied($t_ARRAY, "${Package}::$array_name",
# sizeof($array_type) , $array_size,
# ) ;
# XSRETURN(1);
#]]
--- 1914,1920 ----
#
# ST(0) = Ref2Tied($t_ARRAY, "${Package}::$array_name",
# sizeof($array_type) , $array_size,
# ) ;
# XSRETURN(1);
#]]
***************
*** 2038,2044 ****
#
# ST(0) = Ref2Tied($t_SCALAR, "${Package}::$scalar_name",
# sizeof($scalar_type), 1,
# ) ;
# XSRETURN(1);
#]]
--- 2123,2129 ----
#
# ST(0) = Ref2Tied($t_SCALAR, "${Package}::$scalar_name",
# sizeof($scalar_type), 1,
# ) ;
# XSRETURN(1);
#]]
***************
*** 2202,2207 ****
--- 2287,2293 ----
#int type ;
#char * name ;
#unsigned size ;
+ #unsigned count ;
#void * pointer ;
#int clone ;
#[[
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Ilya Zakharevich writes:
>
> What I'm missing a lot is FIRSTKEY and friends, to make examination of
> structures from debugger simpler.
>

I have it now. Examination ('x') in debugger works OK.

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Paul Marquess writes:
> Thanks for the patch Ilya, and good to see someone having a go with the
> new xsubpp stuff.
>
> It will be a while before I get the chance to go through it in any
> detail, as I am trying to concentrate on finishing off the source
> filters in my limited spare time just now.
>

While Paul is busy, may anyone comment on the following two topics:

a) The original xsubpp-2 returned a (struct blah *)NULL as a structure
filled with zeros, and to recognize this situation one (probably)
needed to check that answer->addressof == 0. I was too lazy, and
corrected the sourse to return undef in this case. Anyone thinking
that this may hurt you? What is lost is the type info.

b) Currently, if we have
struct a
struct b *first
struct b *second
and a.first == a.second, then the current implementation will return
two _different_ SV for $a->{first} and $a->{second}. To check for
equality one need to check
$a->{first}->addresof == $a->{second}->addressof.
With some overhead it is easy to implement a scheme when
$a->{first} eq $a->{second}.
Should we go for this, or leave it as it is?

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
>
> I tried my own ("real life") extension, and now it compiles and runs
> (not sure that it does it correct, though). I needed some additions to
> the posted code.

Thanks for the patch Ilya, and good to see someone having a go with the
new xsubpp stuff.

It will be a while before I get the chance to go through it in any
detail, as I am trying to concentrate on finishing off the source
filters in my limited spare time just now.

The ability to support typedefs was on my list of things to do.

>
> What I'm missing a lot is FIRSTKEY and friends, to make examination of
> structures from debugger simpler.

I see from your followup message that you seem to have got around this
problem.

Expect a proper followup once I've finished source filters.

Paul
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
>
> Paul Marquess writes:
> > Thanks for the patch Ilya, and good to see someone having a go with the
> > new xsubpp stuff.
> >
> > It will be a while before I get the chance to go through it in any
> > detail, as I am trying to concentrate on finishing off the source
> > filters in my limited spare time just now.
> >
>
> While Paul is busy, may anyone comment on the following two topics:

I guess I'm not *that* busy :-)

> a) The original xsubpp-2 returned a (struct blah *)NULL as a structure
> filled with zeros, and to recognize this situation one (probably)
> needed to check that answer->addressof == 0. I was too lazy, and
> corrected the sourse to return undef in this case. Anyone thinking
> that this may hurt you? What is lost is the type info.

Exactly, the type information gets lost.

Hmmm, it *might* not be that big a deal though. When assigning
structure pointers the code would need to know that undef equates to
the null pointer.

Say you have

struct a
struct b *first
struct b *second

and first is NULL. Having xsubpp return undef would allow you to this

if ($a->{first}) { then not NULL }

Now if you have

$b->{first} = $a->{first}

that will be equivalent to this

$b->{first} = undef ;

Currently that won't work, but it could be made to work. I'll put that
on my xsubpp todo list and think about it some more when I'm in xsubpp
mode. I'm not 100% certain that the loss of type information is going
to break something else.


> b) Currently, if we have
> struct a
> struct b *first
> struct b *second
> and a.first == a.second, then the current implementation will return
> two _different_ SV for $a->{first} and $a->{second}. To check for
> equality one need to check
> $a->{first}->addresof == $a->{second}->addressof.
> With some overhead it is easy to implement a scheme when
> $a->{first} eq $a->{second}.
> Should we go for this, or leave it as it is?

The first thing needed would be the logic to detect the possible
duplicate pointers. This is probably doable, but would mean a
performance hit.

Assume that when a.first == a.second, xsubpp can arrange for them
to refer to the same SV. So now you can use the test

$a->{first} eq $a->{second}

Now consider what happens when you want one of the elements to point to
something else (assume $b->{third} is the same type as $a->{first})

$a->{first} = $b->{third}

Oops, $a->{second} will now point to the same thing as $a->{first}. I'm
not sure (without giving it some more thought) if it would be possible
or practical for there to be logic to "do the right thing" in this
case. Have you something in mind?

Back to source filters :-)

Paul
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
Paul Marquess writes:
> > b) Currently, if we have
> > struct a
> > struct b *first
> > struct b *second
> > and a.first == a.second, then the current implementation will return
> > two _different_ SV for $a->{first} and $a->{second}. To check for
> > equality one need to check
> > $a->{first}->addresof == $a->{second}->addressof.
> > With some overhead it is easy to implement a scheme when
> > $a->{first} eq $a->{second}.
> > Should we go for this, or leave it as it is?
>
> The first thing needed would be the logic to detect the possible
> duplicate pointers. This is probably doable, but would mean a
> performance hit.
>
> Assume that when a.first == a.second, xsubpp can arrange for them
> to refer to the same SV. So now you can use the test
>
> $a->{first} eq $a->{second}
>
> Now consider what happens when you want one of the elements to point to
> something else (assume $b->{third} is the same type as $a->{first})
>
> $a->{first} = $b->{third}
>
> Oops, $a->{second} will now point to the same thing as $a->{first}.

Why? Should not $a->{first} = whatever leave $a->{second} intact? If I
understand correct, $a->{first} just corresponds to a.first, right?

Probably I'm missing something.

Ilya
Re: xsubpp2a1: XSUB + C structures, alpha release 1 [ In reply to ]
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
>
> Paul Marquess writes:
> > > b) Currently, if we have
> > > struct a
> > > struct b *first
> > > struct b *second
> > > and a.first == a.second, then the current implementation will return
> > > two _different_ SV for $a->{first} and $a->{second}. To check for
> > > equality one need to check
> > > $a->{first}->addresof == $a->{second}->addressof.
> > > With some overhead it is easy to implement a scheme when
> > > $a->{first} eq $a->{second}.
> > > Should we go for this, or leave it as it is?
> >
> > The first thing needed would be the logic to detect the possible
> > duplicate pointers. This is probably doable, but would mean a
> > performance hit.
> >
> > Assume that when a.first == a.second, xsubpp can arrange for them
> > to refer to the same SV. So now you can use the test
> >
> > $a->{first} eq $a->{second}
> >
> > Now consider what happens when you want one of the elements to point to
> > something else (assume $b->{third} is the same type as $a->{first})
> >
> > $a->{first} = $b->{third}
> >
> > Oops, $a->{second} will now point to the same thing as $a->{first}.
>
> Why? Should not $a->{first} = whatever leave $a->{second} intact? If I
> understand correct, $a->{first} just corresponds to a.first, right?

Correct. I was talking nonsense :-)

> Probably I'm missing something.

Nope, I was.

Paul