June 22, 2005
On Wed, 22 Jun 2005 02:16:15 -0500, Chris Sauls wrote:

> Charles Hixson wrote:
>>    Type GoalRange is Integer range 0...MaxGoal;
>>    Type Goals is array (GoalRange) of Goal;
>> 
>> then it's a compilation error if you index the array with a variable of any type other than GoalRange.  This isn't necessary in order to
> 
> Couldn't you just use a static array?  Or am I missing something?
> 
Static or Dynamic, it doesn't matter.

It would be used in situations like this ...

   typedef int WidgetId;
   typedef int Dimension;

   class Widget { . . . }

   Widget[cast(WidgetId)] KnownWidgets;
   Dimension x,y,z;
   . . .
   KnownWidgets[ x ].Hide(); // This should fail as it's index
                             // is a 'Dimension' and not a 'WidgetId'



-- 
Derek Parnell
Melbourne, Australia
22/06/2005 7:33:51 PM
June 22, 2005
Derek Parnell wrote:
>    Widget[cast(WidgetId)] KnownWidgets;
>    Dimension x,y,z;
>    . . .
>    KnownWidgets[ x ].Hide(); // This should fail as it's index
>                              // is a 'Dimension' and not a 'WidgetId'

Okay, I get it now... odd, but I guess its like another kind of contract.

-- Chris Sauls
June 22, 2005
Regan Heath wrote:
> On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson  <charleshixsn@earthlink.net> wrote:
>> Regan Heath wrote:
>>> On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson   <charleshixsn@earthlink.net> wrote:
>>>> Jarrett Billingsley wrote:
>>>>> "Charles Hixson" <charleshixsn@earthlink.net> wrote in message   news:d950du$2u4c$1@digitaldaemon.com...
>>>>>
>>>>>> Does:
>>>>>> typedef int MyType;
>>>>>> char[MyType] val;
>>>>>>
>>>>>> result in val being an associative array, rather than an arrays  whose  indicies are typechecked to be instances of MyType?
>>>>>   Yes.  Any time you put _any_ kind of type inside the brackets,  it's  an AA. This works too:
>>>>>  char[int] val;
>>>>>  val is an AA of chars indexed by ints.  I think an AA with an int  key  is usually called a "sparse array."
>>>> Thanks for the info.
>>>>
>>>> Unfortunately, what I wanted wasn't a sparse array, but an array that   required it's indexes to be a particular type... O, well. At other  times  I want sparse arrays...so that's all to the good.
>>>>
>>>> Any suggestions as to how to require indexes to be of a particular   type?  (All I can think of is building a class, and implementing   optAssign, etc.)
>>>  I dont understand what you want. It seems like you're saying you want  a  normal array i.e. sequentialy indexed items and you want to limit  which  type can be used to index it to? why?
>>>  I'd guess you have something like:
>>>  class Bar{}
>>> enum Foo {
>>>  A,B,C,D,E,F,G
>>> }
>>> Bar[G] data;
>>>  and you're trying to get the compiler to limit the indices to the  'data'  array to the enumerated type, or similar.
>>>  Am I on the right track?
>>>  Regan
>> Sort of right.  I'm translating a program from Ada (learning 2 languages  at once).  In Ada if one defines a type and then defines an array type,  say:
>>     Type GoalRange is Integer range 0...MaxGoal;
>>     Type Goals is array (GoalRange) of Goal;
>>
>> then it's a compilation error if you index the array with a variable of  any type other than GoalRange.  This isn't necessary in order to  translate the program...but it does add a layer of error checking at  compile time that I think useful...
> 
> Yeah, that is basically what I figured you wanted. I agree it would be  useful.
> 
>> *!*IF*!* I can add it without too much work.  (OTOH, Ada doesn't have  built in hash tables...and I've been scratching my head around how to  replace tree searches that aren't well documented [now where is this  "out" variable used...and WHY??].)
> 
> I'm sorry I can't help with Ada. I've never used it.
> 
>> OTOH, replacing GoalRange with an enumeration is a bit ... strange.
> 
> Yeah, but it's the closest built in basic type to a 'range' that D has I  reckon. I D got ranges I'd imagine them built onto the enum syntax eg.
> 
> enum myInt : int { 0,...,100 }
> enum myInt : int { 0 ... 100 }
> 
> or something similar.
> 
> There have been a number of requests for a range type in D, I can't  remember Walter's position (or even if he gave one). I suspect at this  stage 'ranges', while useful, are not high on the list of things to do.
> 
>> OTOH, a sparse array / hash table is definitely NOT what I want where  I'm just looking to enforce type safety.  (But I sure do want it at  other times!)
> 
> Sure, they're kind of overkill really for this problem. Tho, they'd do the  job, right?
> 
> Regan
They won't even "really" do the job...though I guess they could, as long as you could distinguish null from out-of-range.  But hash tables aren't intended for stepping through, and arrays are.  You could force them to do the job...but that would be worse than writing a new container class (which looks to be relatively minor), and would probably be much more inefficient.  (Done right, all the overhead [over an array of integers] should be at compile time.)

Still, this really IS minor.  I can skip the layer of error checking, and use alias instead of typedef...or I can write the container classes (which might be good practice anyway).  But I'd need to write it several times, because I'm NOT ready to start dealing with templates yet.  (For some reason, that's the feature of D that makes less sense to me than any of the others.  I far prefer the way that Eiffel uses generics [or did 5 years ago] to handle the same problem.)

June 22, 2005
Derek Parnell wrote:
> On Tue, 21 Jun 2005 20:37:44 -0700, Charles Hixson wrote:
> 
>> Derek Parnell wrote:
>>> On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson wrote:
>>>
>>>> Jarrett Billingsley wrote:
>>>>> "Charles Hixson" <charleshixsn@earthlink.net> wrote in message news:d950du$2u4c$1@digitaldaemon.com...
>>>>>
>>>>>> Does:
>>>>>> typedef int MyType;
>>>>>> char[MyType] val;
>>>>>>
>>>>>> result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?
>>>>> Yes.  Any time you put _any_ kind of type inside the brackets, it's an AA. This works too:
>>>>>
>>>>> char[int] val;
>>>>>
>>>>> val is an AA of chars indexed by ints.  I think an AA with an int key is usually called a "sparse array." 
>>>>>
>>>>>
>>>> Thanks for the info.
>>>>
>>>> Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good.
>>>>
>>>> Any suggestions as to how to require indexes to be of a particular type?  (All I can think of is building a class, and implementing optAssign, etc.)
>>> Maybe a struct might be useful ...
>>>
>>> struct arrtype
>>> {
>>>     int x;
>>> }
>>>
>>> void main()
>>> {
>>>     char[][ arrtype ] c;
>>>         arrtype a,b;
>>>     a.x = 1;
>>>     b.x = 2;
>>>     c[a] = "one";
>>>     c[b] = "two";
>>> }
>>>
>> But doesn't that still give you a hash table / sparse array?
>> No, I think what I need to do (if I decide it's worth it) is create a class and implement opIndex, opIndexAssign, and possibly opSlice (two versions).  That would (apparently?) allow me to specify the index type required...but that's a bit heavy duty just to implement a bit of type checking...so I'll probably skip that unless I find an easier way, or unless I find another reason to create it as a class.
> 
> Sorry, I misunderstood. 
> 
> So you want a standard array, that is one in which the index is an offset
> from the start of the array, but you want to specify that only certain
> types of integers are allowed as indexes in array references.
> 
> Sounds like a useful idea; a natural extension of static type checking.
> 
Yeah.  But the syntax of how to do it is the problem.  I think I agree that hash tables are a more important use for the syntax. Up until now I'd been confused about just WHAT would happen if I declared an array with an integer type, possibly partially BECAUSE Ada used it for type checking...which seems to me a straight-forward interpretation of the syntax, just not the most useful one.  Hash tables have more general utility, but error checking is also high priority...it would be nice to have BOTH. Unfortunately, just how to do it isn't terribly clear.

Possibly range types are the answer.  This would require simple syntax to specify open-ended (well, sort of) ranges.  Then one could adopt the convention that arrays indexed by a range were normal arrays with a range index.  (But then how would one make a  hash table over a range?)

One obvious answer is to adopt a new keyword in the special limited context of array declarations, thus:
typedef	short	Entry;
int[indexed by Entry] checkedItems;

This would work, and is clear, but requires the new keyword "indexed by" within the context of an array declaration.  This isn't as bad as it might be, as it wouldn't break any existing code...but it does make things more complicated.


June 22, 2005
On Wed, 22 Jun 2005 08:21:06 -0700, Charles Hixson <charleshixsn@earthlink.net> wrote:
> Regan Heath wrote:
>> On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson  <charleshixsn@earthlink.net> wrote:
>>> Regan Heath wrote:
>>>> On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson   <charleshixsn@earthlink.net> wrote:
>>>>> Jarrett Billingsley wrote:
>>>>>> "Charles Hixson" <charleshixsn@earthlink.net> wrote in message   news:d950du$2u4c$1@digitaldaemon.com...
>>>>>>
>>>>>>> Does:
>>>>>>> typedef int MyType;
>>>>>>> char[MyType] val;
>>>>>>>
>>>>>>> result in val being an associative array, rather than an arrays  whose  indicies are typechecked to be instances of MyType?
>>>>>>   Yes.  Any time you put _any_ kind of type inside the brackets,  it's  an AA. This works too:
>>>>>>  char[int] val;
>>>>>>  val is an AA of chars indexed by ints.  I think an AA with an int  key  is usually called a "sparse array."
>>>>> Thanks for the info.
>>>>>
>>>>> Unfortunately, what I wanted wasn't a sparse array, but an array that   required it's indexes to be a particular type... O, well. At other  times  I want sparse arrays...so that's all to the good.
>>>>>
>>>>> Any suggestions as to how to require indexes to be of a particular   type?  (All I can think of is building a class, and implementing   optAssign, etc.)
>>>>  I dont understand what you want. It seems like you're saying you want  a  normal array i.e. sequentialy indexed items and you want to limit  which  type can be used to index it to? why?
>>>>  I'd guess you have something like:
>>>>  class Bar{}
>>>> enum Foo {
>>>>  A,B,C,D,E,F,G
>>>> }
>>>> Bar[G] data;
>>>>  and you're trying to get the compiler to limit the indices to the  'data'  array to the enumerated type, or similar.
>>>>  Am I on the right track?
>>>>  Regan
>>> Sort of right.  I'm translating a program from Ada (learning 2 languages  at once).  In Ada if one defines a type and then defines an array type,  say:
>>>     Type GoalRange is Integer range 0...MaxGoal;
>>>     Type Goals is array (GoalRange) of Goal;
>>>
>>> then it's a compilation error if you index the array with a variable of  any type other than GoalRange.  This isn't necessary in order to  translate the program...but it does add a layer of error checking at  compile time that I think useful...
>>  Yeah, that is basically what I figured you wanted. I agree it would be  useful.
>>
>>> *!*IF*!* I can add it without too much work.  (OTOH, Ada doesn't have  built in hash tables...and I've been scratching my head around how to  replace tree searches that aren't well documented [now where is this  "out" variable used...and WHY??].)
>>  I'm sorry I can't help with Ada. I've never used it.
>>
>>> OTOH, replacing GoalRange with an enumeration is a bit ... strange.
>>  Yeah, but it's the closest built in basic type to a 'range' that D has I  reckon. I D got ranges I'd imagine them built onto the enum syntax eg.
>>  enum myInt : int { 0,...,100 }
>> enum myInt : int { 0 ... 100 }
>>  or something similar.
>>  There have been a number of requests for a range type in D, I can't  remember Walter's position (or even if he gave one). I suspect at this  stage 'ranges', while useful, are not high on the list of things to do.
>>
>>> OTOH, a sparse array / hash table is definitely NOT what I want where  I'm just looking to enforce type safety.  (But I sure do want it at  other times!)
>>  Sure, they're kind of overkill really for this problem. Tho, they'd do the  job, right?
>>  Regan
> They won't even "really" do the job...though I guess they could, as long as you could distinguish null from out-of-range.  But hash tables aren't intended for stepping through, and arrays are.   You could force them to do the job...but that would be worse than writing a new container class (which looks to be relatively minor), and would probably be much more inefficient.  (Done right, all the overhead [over an array of integers] should be at compile time.)
>
> Still, this really IS minor.  I can skip the layer of error checking, and use alias instead of typedef...or I can write the container classes (which might be good practice anyway).  But I'd need to write it several times, because I'm NOT ready to start dealing with templates yet.  (For some reason, that's the feature of D that makes less sense to me than any of the others.  I far prefer the way that Eiffel uses generics [or did 5 years ago] to handle the same problem.)

Just for fun if you post the container here I'll try and turn it into a template class.

June 24, 2005
Regan Heath wrote:
> On Wed, 22 Jun 2005 08:21:06 -0700, Charles Hixson  <charleshixsn@earthlink.net> wrote:
>> Regan Heath wrote:
>>> On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson   <charleshixsn@earthlink.net> wrote:
>>>> Regan Heath wrote:
>>>>> On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson    <charleshixsn@earthlink.net> wrote:
>>>>>> Jarrett Billingsley wrote:
>>>>>>> "Charles Hixson" <charleshixsn@earthlink.net> wrote in message    news:d950du$2u4c$1@digitaldaemon.com...
>>>>>>>
>>>>>>>> Does:
>>>>>>>> typedef int MyType;
>>>>>>>> char[MyType] val;
>>>>>>>>
>>>>>>>> result in val being an associative array, rather than an arrays   whose  indicies are typechecked to be instances of MyType?
>>>>>>>   Yes.  Any time you put _any_ kind of type inside the brackets,   it's  an AA. This works too:
>>>>>>>  char[int] val;
>>>>>>>  val is an AA of chars indexed by ints.  I think an AA with an int   key  is usually called a "sparse array."
>>>>>> Thanks for the info.
>>>>>>
>>>>>> Unfortunately, what I wanted wasn't a sparse array, but an array  that   required it's indexes to be a particular type... O, well. At  other  times  I want sparse arrays...so that's all to the good.
>>>>>>
>>>>>> Any suggestions as to how to require indexes to be of a particular    type?  (All I can think of is building a class, and implementing    optAssign, etc.)
>>>>>  I dont understand what you want. It seems like you're saying you  want  a  normal array i.e. sequentialy indexed items and you want to  limit  which  type can be used to index it to? why?
>>>>>  I'd guess you have something like:
>>>>>  class Bar{}
>>>>> enum Foo {
>>>>>  A,B,C,D,E,F,G
>>>>> }
>>>>> Bar[G] data;
>>>>>  and you're trying to get the compiler to limit the indices to the   'data'  array to the enumerated type, or similar.
>>>>>  Am I on the right track?
>>>>>  Regan
>>>> Sort of right.  I'm translating a program from Ada (learning 2  languages  at once).  In Ada if one defines a type and then defines an  array type,  say:
>>>>     Type GoalRange is Integer range 0...MaxGoal;
>>>>     Type Goals is array (GoalRange) of Goal;
>>>>
>>>> then it's a compilation error if you index the array with a variable  of  any type other than GoalRange.  This isn't necessary in order to   translate the program...but it does add a layer of error checking at   compile time that I think useful...
>>>  Yeah, that is basically what I figured you wanted. I agree it would  be  useful.
>>>
>>>> *!*IF*!* I can add it without too much work.  (OTOH, Ada doesn't have   built in hash tables...and I've been scratching my head around how to   replace tree searches that aren't well documented [now where is this   "out" variable used...and WHY??].)
>>>  I'm sorry I can't help with Ada. I've never used it.
>>>
>>>> OTOH, replacing GoalRange with an enumeration is a bit ... strange.
>>>  Yeah, but it's the closest built in basic type to a 'range' that D has  I  reckon. I D got ranges I'd imagine them built onto the enum syntax  eg.
>>>  enum myInt : int { 0,...,100 }
>>> enum myInt : int { 0 ... 100 }
>>>  or something similar.
>>>  There have been a number of requests for a range type in D, I can't   remember Walter's position (or even if he gave one). I suspect at this   stage 'ranges', while useful, are not high on the list of things to do.
>>>
>>>> OTOH, a sparse array / hash table is definitely NOT what I want where   I'm just looking to enforce type safety.  (But I sure do want it at   other times!)
>>>  Sure, they're kind of overkill really for this problem. Tho, they'd do  the  job, right?
>>>  Regan
>> They won't even "really" do the job...though I guess they could, as long  as you could distinguish null from out-of-range.  But hash tables aren't  intended for stepping through, and arrays are.   You could force them to  do the job...but that would be worse than writing a new container class  (which looks to be relatively minor), and would probably be much more  inefficient.  (Done right, all the overhead [over an array of integers]  should be at compile time.)
>>
>> Still, this really IS minor.  I can skip the layer of error checking,  and use alias instead of typedef...or I can write the container classes  (which might be good practice anyway).  But I'd need to write it several  times, because I'm NOT ready to start dealing with templates yet.  (For  some reason, that's the feature of D that makes less sense to me than  any of the others.  I far prefer the way that Eiffel uses generics [or  did 5 years ago] to handle the same problem.)
> 
> Just for fun if you post the container here I'll try and turn it into a  template class.
> 
OK, here it is.  Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access.  There seem to be type problems that I don't understand.  (Sample use at the end.)
I haven't tested the code yet beyond getting it to compile, but it's hardly a complete application.

typedef	uint	SymbolId;
typedef	uint	IndexId;
typedef	char[]	Token;
class Symbols
{
protected
   class   Symbol
   {  Token      token;
      SymbolId   symbolId;
      bit      arithme;
      bit      defined;
      float      value;
      IndexId   indexId;

      this   (Token   t)
      {   token   =   t;
         symbolId   =   cast(SymbolId)symbols.length;
      }
   }
   SymbolId   nxtSymbolId   =   0;
   Symbol[]      symbols;
   /*   note   that   the   symbNdx   hash   table   can   be rebuilt   as   needed
      *   from   the   symbols   array.      Thus   it   need not   be   saved.
      */
   SymbolId[Token]   symbNdx;
   invariant
   {   //   does   nxtSymbolId   have   any   other   use? If   so,   why?
      assert   (nxtSymbolId   ==   symbols.length);
      //   Make   sure   the   index   is   kept   current
      assert   (symbols.length   ==   symbNdx.length);
   }
   bit   search(Symbol   symbol)
   {   return   search(symbol.token);   }
public
   //this   ()   {   super();   }
   this   ()      {   }
   bit   search(SymbolId   symbolId)
   {   if   (symbolId   >=   symbols.length)   return   false;
      if   (symbols[symbolId]   !is   null)
         assert(symbols[symbolId].symbolId   ==   symbolId);
      return   (symbols[symbolId]   !is   null);
   }
   bit   search(Token   token)
   {   return   search(symbNdx[token]);   }
   this(char[]   name)
   {
   }
   Token   optIndex(SymbolId   symbolId)
   {   if   (symbolId   >=   symbols.length)   return   null;
      return   symbols[symbolId].token;
   }
   SymbolId   optIndex(Token   token)
   {   assert   (token   !is   null);
      return   symbNdx[token];
   }

   void   optCatAssign(Token   token)
   in   {   assert   (token   !is   null);   }
   body
   {   Symbol   symb;
      if   (search   (token)   )
      {   //   do   we   really   want   to   allow   symbols to   be   redefined?
         throw   new   SymbolException
                     ("attempt   to   redefine   existing symbol");
      }
      else
      {   nxtSymbolId   +=   1;
         symbNdx[token]   =   cast(SymbolId)symbols.length;
         symbols   ~=   new   Symbol(token);
      }
   }
   void   append(Token   token)
   in   {   assert   (token   !is   null);   }
   body
   {   Symbol   symb;
      if   (search   (token)   )
      {   //   do   we   really   want   to   allow   symbols to   be   redefined?
         throw   new   SymbolException
                     ("attempt   to   redefine   existing symbol");
      }
      else
      {   nxtSymbolId   +=   1;
         symbNdx[token]   =   cast(SymbolId)symbols.length;
         symbols   ~=   new   Symbol(token);
      }
   }

}

++++++++++++++++++++++++ in a new file ++++++++++++++++++++++++

import	symbol;
SymbolId   makeSym(inout   Symbols   symbols,   in   Token   phrase)
{   symbols.append(phrase);
   //return   symbols[cast(Token)phrase];
   return   symbols.optIndex(phrase);
}
June 24, 2005
On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson <charleshixsn@earthlink.net> wrote:
> OK, here it is.  Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access.  There seem to be type problems that I don't understand.  (Sample use at the end.)

It's opIndex, not optIndex, that's why it wasn't working.

> I haven't tested the code yet beyond getting it to compile, but it's hardly a complete application.

Missing was TokenException (I defined one). I'll see what I come up with, no promises :)

Regan

p.s. the code below is really weirdly formatted, extra double spaced everywhere.. was that intentional or a result of the NG?

> typedef	uint	SymbolId;
> typedef	uint	IndexId;
> typedef	char[]	Token;
> class Symbols
> {
> protected
>     class   Symbol
>     {  Token      token;
>        SymbolId   symbolId;
>        bit      arithme;
>        bit      defined;
>        float      value;
>        IndexId   indexId;
>
>        this   (Token   t)
>        {   token   =   t;
>           symbolId   =   cast(SymbolId)symbols.length;
>        }
>     }
>     SymbolId   nxtSymbolId   =   0;
>     Symbol[]      symbols;
>     /*   note   that   the   symbNdx   hash   table   can   be rebuilt   as   needed
>        *   from   the   symbols   array.      Thus   it   need not   be   saved.
>        */
>     SymbolId[Token]   symbNdx;
>     invariant
>     {   //   does   nxtSymbolId   have   any   other   use? If   so,   why?
>        assert   (nxtSymbolId   ==   symbols.length);
>        //   Make   sure   the   index   is   kept   current
>        assert   (symbols.length   ==   symbNdx.length);
>     }
>     bit   search(Symbol   symbol)
>     {   return   search(symbol.token);   }
> public
>     //this   ()   {   super();   }
>     this   ()      {   }
>     bit   search(SymbolId   symbolId)
>     {   if   (symbolId   >=   symbols.length)   return   false;
>        if   (symbols[symbolId]   !is   null)
>           assert(symbols[symbolId].symbolId   ==   symbolId);
>        return   (symbols[symbolId]   !is   null);
>     }
>     bit   search(Token   token)
>     {   return   search(symbNdx[token]);   }
>     this(char[]   name)
>     {
>     }
>     Token   optIndex(SymbolId   symbolId)
>     {   if   (symbolId   >=   symbols.length)   return   null;
>        return   symbols[symbolId].token;
>     }
>     SymbolId   optIndex(Token   token)
>     {   assert   (token   !is   null);
>        return   symbNdx[token];
>     }
>
>     void   optCatAssign(Token   token)
>     in   {   assert   (token   !is   null);   }
>     body
>     {   Symbol   symb;
>        if   (search   (token)   )
>        {   //   do   we   really   want   to   allow   symbols to   be   redefined?
>           throw   new   SymbolException
>                       ("attempt   to   redefine   existing symbol");
>        }
>        else
>        {   nxtSymbolId   +=   1;
>           symbNdx[token]   =   cast(SymbolId)symbols.length;
>           symbols   ~=   new   Symbol(token);
>        }
>     }
>     void   append(Token   token)
>     in   {   assert   (token   !is   null);   }
>     body
>     {   Symbol   symb;
>        if   (search   (token)   )
>        {   //   do   we   really   want   to   allow   symbols to   be   redefined?
>           throw   new   SymbolException
>                       ("attempt   to   redefine   existing symbol");
>        }
>        else
>        {   nxtSymbolId   +=   1;
>           symbNdx[token]   =   cast(SymbolId)symbols.length;
>           symbols   ~=   new   Symbol(token);
>        }
>     }
>
> }
>
> ++++++++++++++++++++++++ in a new file ++++++++++++++++++++++++
>
> import	symbol;
> SymbolId   makeSym(inout   Symbols   symbols,   in   Token   phrase)
> {   symbols.append(phrase);
>     //return   symbols[cast(Token)phrase];
>     return   symbols.optIndex(phrase);
> }

June 24, 2005
On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson wrote:


[snip]
> OK, here it is.  Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access.

Should be "op" rather than "opt". However the opCatAssign() will not work until Walter allows us to concatenate things that are not arrays. If you define opCatAssign() and then use "x ~= y" where 'y' is not an array or an element of 'x', the compiler complains.

Anyhow, here is the result of my playing around with your code.
I added opIndex(int) to make using symbols[int] easier, and a Count()
method.

<code for file symbol.d>
typedef	uint	SymbolId;
typedef	uint	IndexId;
typedef	char[]	Token;
class SymbolException
{
    char[] m_msg;
    this(char[] msg)
    {
        m_msg = msg.dup;
    }
}

class Symbols
{
    protected:
        struct Symbol
        {
            Token  token;
            SymbolId symbolId;
            bit  arithme;
            bit  defined;
            float  value;
            IndexId indexId;

            void Init(Token t)
            {
                token = t;
                symbolId = nxtSymbolId;
            }
        }
        static SymbolId nxtSymbolId = 0;
        Symbol[] lSymbolList;

    /*  note that the symbNdx hash table can be
        rebuilt as needed from the symbols array. Thus it need
        not be saved.
    */
        SymbolId[Token] symbNdx;

        void AddSymbol(Token pToken)
        {
            nxtSymbolId += 1;
            symbNdx[pToken] = nxtSymbolId;
            lSymbolList.length = lSymbolList.length + 1;
            lSymbolList[$-1].Init(pToken);
        }

    invariant
    {
        // Make sure the index is kept current
        assert (lSymbolList.length == symbNdx.length);
    }

    bit search(Symbol symbol)
    {
        return search(symbol.token);
    }

    public:
    this ()  { }
    bool search(SymbolId pSymbolId)
    {
        if (pSymbolId >= nxtSymbolId)
            return false;
        if (pSymbolId >= lSymbolList.length)
            return false;

        assert(lSymbolList[pSymbolId].symbolId == pSymbolId);
        return true;
    }

    bool search(Token token)
    {
        return (token in symbNdx) is null ? false : true;
    }

    Token opIndex(SymbolId symbolId)
    {
        if (symbolId >= lSymbolList.length)
            return null;
        return lSymbolList[symbolId].token;
    }

    SymbolId opIndex(Token token)
    {
        assert (token !is null);
        return symbNdx[token];
    }

    Token opIndex(int pIdx)
    {
        assert(pIdx >= 0 && pIdx < lSymbolList.length);
        return lSymbolList[pIdx].token;
    }

    SymbolId append(Token token)
    in { assert (token !is null); }
    body
    {
        Symbol symb;
        if (search (token) )
        { // do we really want to allow symbols to be redefined?
            throw new SymbolException("attempt to redefine existing
symbol");
        }

        AddSymbol(token);
        return nxtSymbolId;
    }

    int Count()
    {
        return lSymbolList.length;
    }

}
</code>


<code for test.d>
import std.stdio;
import symbol;

void main()
{
    Symbols lBase = new Symbols;

    lBase.append(cast(Token)"if");
    lBase.append(cast(Token)"static");
    lBase.append(cast(Token)"static if");

    for(int i = 0; i < lBase.Count; i++)
    {
        writefln("Symbol id %d: '%s'", i, lBase[i]);
    }

}</code>



-- 
Derek
Melbourne, Australia
24/06/2005 11:18:46 AM
June 24, 2005
After a brief look I'm not quite sure where to start.

I see Symbols  (the container class)
I see Symbol   (created to hold a Token, and SymbolId)
I see Token    (an object)
I see SymbolId (ever incrementing, always unique id for a Symbol)
I see IndexId  (not used?)

You said "But I'd need to write it several times", what parts change for the next time?

Regan
June 24, 2005
Regan Heath wrote:
> On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson  <charleshixsn@earthlink.net> wrote:
>> OK, here it is.  Note that I had to define append rather than using  optCatAssign, and I have to call optIndex as a function rather than  using [] access.  There seem to be type problems that I don't  understand.  (Sample use at the end.)
> 
> It's opIndex, not optIndex, that's why it wasn't working.
> 
>> I haven't tested the code yet beyond getting it to compile, but it's  hardly a complete application.
> 
> Missing was TokenException (I defined one). I'll see what I come up with,  no promises :)
> 
> Regan
> 
> p.s. the code below is really weirdly formatted, extra double spaced  everywhere.. was that intentional or a result of the NG?
> 
Well the original code was single spaced, tab delimited @ 3 spaces = one tab.  (I pasted that into the email, and then did a global replace of tabs with 3 spaces...not good, but the starts of lines should be OK.)  My guess was that most of the lines were too long, and the messaging processes split the lines somewhere along the path.

(TokenException doesn't do anything special except say "This is a token exception with the following message:  xxxxx" ... only of course, not literally that.  Nearly anything you defined it as should work adequately.)