[Prev][Index]

SAGE++ C++ unparse fixes




Dennis,
        I had been having problems with templates, and finally
(yesterday) decided to try to fix them myself.  This required FOUR
changes to unparse.c and unparseC++.def.  The problems show up when
parsing/unparsing the following example.

The FOUR code fixes are given below, along with explanations of why I
believe they are necessary.  You may want to look at these and see if
it fits into the design of the unparser.

Hope these help.  Sage++ is great and I wanna make it better!

        -Tom


Example program that illustrates broken unparser --
================================================================
template <class T> class v {
    T val;
    int segd;
};

typedef v<int> vint;

main() 
{

    v<int> thing;
    v<int> &refthing;
    v<v<int> > nest;
    v<v<int> > &nest2;
    vint   thing2;
    vint   &thing2ref;
    int    &intref;
}
================================================================


Fix #1:  file "unparse.c"  function "Find_BaseType"
        Added the line indicated

        ...
          if (TYPE_CODE(pt) == T_DERIVED_COLLECTION) break;
          if (TYPE_CODE(pt) == T_DERIVED_CLASS) break;
          /* TOM: added this line */
          if (TYPE_CODE(pt) == T_DERIVED_TEMPLATE) break;
          if (TYPE_CODE(pt) == T_CLASS) break;
          if (TYPE_CODE(pt) == T_COLLECTION) break;
        ...


Fix #2: file "unparseC++.def"  terminal "T_DERIVED_TEMPLATE"
        - added a space before the '>' 
        - necessary when nesting templates:  v<v<int > >

         DEFNODECODE(T_DERIVED_TEMPLATE, "%SYMBID%SETFLAG(TMPLDEC)%PUSHFLAG(PAREN)<%TMPLARGS >%POPFLAG(PAREN)%UNSETFLAG(TMPLDEC)", 
't',0,TYPENODE) 


Fix #3: file 'unparse.c' function 'Tool_Unparse_Type"
        - template names were printed with global scope operator, i.e. "::v<int>"
        - I don't think C++ allows template names to be scoped (which is weird!!)
        - special case added for templates

        - Replaced the following
         if(TYPE_SCOPE_SYMB_DERIVE(ptype)) {
                         Tool_Unparse_Symbol(TYPE_SCOPE_SYMB_DERIVE(ptype));
                         BufPutString("::",0);
                         }


        with 
        if(TYPE_SCOPE_SYMB_DERIVE(ptype) && TYPE_CODE(ptype) != T_DERIVED_TEMPLATE) {
                         Tool_Unparse_Symbol(TYPE_SCOPE_SYMB_DERIVE(ptype));
                         BufPutString("::",0);
                         }


Fix #4: file 'unparseC++.def' terminal T_DERIVED_TEMPLATE
        - added PUSHFLAG(PAREN) ... POPFLAG(PAREN)

 DEFNODECODE(T_DERIVED_TEMPLATE, "%SYMBID%SETFLAG(TMPLDEC)%PUSHFLAG(PAREN)<%TMPLARGS >%POPFLAG(PAREN)%UNSETFLAG(TMPLDEC)", 
't',0,TYPENODE) 

        - explanation: the PAREN flags is set when printing expr
lists, so that if another expr-list occurs inside the outer one, it is
surrounded by parens.  The template args are an expr list, and
whenever a nested template occurred, parens showed up. E.g.

        v<v<(int)>>

The template <> symbols delimit the expr-list inside, so in nested
templates you need to reset the paren flag.