login  home  contents  what's new  discussion  bug reports     help  links  subscribe  changes  refresh  edit

Edit detail for DebuggingFriCAS revision 1 of 2

1 2
Editor: page
Time: 2007/11/12 22:45:21 GMT-8
Note: transferred from axiom-developer.org

changed:
-
Fortunately, Axiom is rather easy to debug. Most of the source is very transparent, so once you have localized the bug there are mostly "design issues":DesignIssues to overcome. However, to find out which function is bugged, there are some helpful tools.
These consist of:

  - inspecting signatures of operations and packages, domains and categories using::
      
       )display operation foo
       )show mydomain

  - seeing which functions are called using ')set message bottom on'

  - using the "trace facility":HyperDocTracing

Let's use the following might-be-bug as a running example:

\begin{axiom}
variables((x^2+2*x)::UP(x, INT))
\end{axiom}

Certainly, this is not what one would expect. So, let's find out more about 'variables'! 

One way to find all files where 'variables' is instantiated is 'grep "variables.*==" *'. It is not totally reliable, but I found it quite useful and it is quickly typed. Another possibility, within Axiom, is to use

\begin{axiom}
)di op variables
\end{axiom}

This is a list of all [exposed] and [unexposed] operations called 'variables', together with their [modelines]. Note that the information that 
')di op' (and all the other tools, like 'asq') give about sourcefiles is currently wrong! I use 'grep ")abb.* UP " *' to find the correct sourcefile. 

In some cases the list of operations is very long. For example, ')di op coerce' lists 168 exposed and 50 unexposed items. Fortunately there is another tool:

\begin{axiom}
)set message bottom on
variables(x::UP(x, INT))
\end{axiom}

Now we know that 'variables' does not come from some package, but rather from 'UP' itself. You might want to compare with

\begin{axiom}
)set message bottom on
variables(x::FRAC POLY INT)
\end{axiom}

Here, 'variables' comes from 'RF'. Another way to watch Axiom looking for functions is ')lisp (setq |$monitorNewWorld| t)', but I don't understand its output too well. More possibilities are discussed in the file 'DeveloperNotes.dvi' in 'axiom/mnt/linux/doc/'. 

Given that 'variables' comes from 'UP', we still don't know where it is actually coded. In fact, there is no code for 'variables' in 'UP'. So, where does Axiom look next? We can find out about this using

'asq -cc UP'

which tells us, that the constructorcategory of 'UP' is 'UPOLYC'. Et voilĂ ::

    )abbrev category UPOLYC UnivariatePolynomialCategory
    ...
    UnivariatePolynomialCategory(R:Ring): Category ==
      add
    ...
        variables(p) ==
          zero? p or zero?(degree p) => []
          [create()]

It also helps to look at the modeline of 'variables', which we can find out using ')sh UP'::

    )sh UP
     UnivariatePolynomial(x: Symbol,R: Ring)  is a domain constructor
     Abbreviation for UnivariatePolynomial is UP 
     This constructor is exposed in this frame.
     Issue )edit /home/rubey/axiom/mnt/linux/../../src/algebra/UP.spad to see algebra source code for UP 
    
    ------------------------------- Operations --------------------------------
    ...
     variables : % -> List SingletonAsOrderedSet
    ...

SingletonAsOrderedSet is a domain which consists of the single element '"?"'! Hence, we have reduced the problem of fixing the bug to a 
"design issue":DesignIssues.

Fortunately, Axiom is rather easy to debug. Most of the source is very transparent, so once you have localized the bug there are mostly design issues to overcome. However, to find out which function is bugged, there are some helpful tools. These consist of:

  • inspecting signatures of operations and packages, domains and categories using:
           )display operation foo
           )show mydomain
    
  • seeing which functions are called using )set message bottom on
  • using the trace facility

Let's use the following might-be-bug as a running example:

axiom
variables((x^2+2*x)::UP(x, INT))

\label{eq1}\left[ \mbox{\tt "?"}\right](1)
Type: List(SingletonAsOrderedSet?)

Certainly, this is not what one would expect. So, let's find out more about variables!

One way to find all files where variables is instantiated is grep "variables.*==" *. It is not totally reliable, but I found it quite useful and it is quickly typed. Another possibility, within Axiom, is to use

axiom
)di op variables
There are 5 exposed functions called variables : [1] D -> List(Symbol) from D if D has FS(D2) and D2 has COMPAR [2] D -> List(D4) from D if D has POLYCAT(D2,D3,D4) and D2 has RING and D3 has OAMONS and D4 has ORDSET [3] D -> List(D4) from D if D has PSCAT(D2,D3,D4) and D2 has RING and D3 has OAMON and D4 has ORDSET [4] D -> List(D4) from D if D has PSETCAT(D2,D3,D4,D5) and D2 has RING and D3 has OAMONS and D4 has ORDSET and D5 has RPOLCAT(D2,D3,D4) [5] Fraction(Polynomial(D3)) -> List(Symbol) from RationalFunction( D3) if D3 has INTDOM
There are 4 unexposed functions called variables : [1] SparseUnivariatePolynomial(D6) -> List(D4) from FactoringUtilities(D3,D4,D5,D6) if D6 has POLYCAT(D5,D3,D4) and D3 has OAMONS and D4 has ORDSET and D5 has RING [2] FortranExpression(D2,D3,D4) -> List(Symbol) from FortranExpression(D2,D3,D4) if D2: LIST(SYMBOL) and D3: LIST(SYMBOL) and D4 has FMTC
[3] Pattern(D2) -> List(Pattern(D2)) from Pattern(D2) if D2 has SETCAT [4] D2 -> List(D4) from PolynomialCategoryQuotientFunctions(D3,D4,D5 ,D6,D2) if D3 has OAMONS and D4 has ORDSET and D5 has RING and D6 has POLYCAT(D5,D3,D4) and D2 has Field with coerce : D6 -> % numer : % -> D6 denom : % -> D6

This is a list of all [exposed]? and [unexposed]? operations called variables, together with their [modelines]?. Note that the information that )di op (and all the other tools, like asq) give about sourcefiles is currently wrong! I use grep ")abb.* UP " * to find the correct sourcefile.

In some cases the list of operations is very long. For example, )di op coerce lists 168 exposed and 50 unexposed items. Fortunately there is another tool:

axiom
)set message bottom on
variables(x::UP(x, INT))
Function Selection for variables Arguments: UP(x,INT)
[1] signature: UP(x,INT) -> LIST(SAOS) implemented: slot (List (SingletonAsOrderedSet))$ from UP(x,INT)

\label{eq2}\left[ \mbox{\tt "?"}\right](2)
Type: List(SingletonAsOrderedSet?)

Now we know that variables does not come from some package, but rather from UP itself. You might want to compare with

axiom
)set message bottom on
variables(x::FRAC POLY INT)
Function Selection for variables Arguments: FRAC(POLY(INT)) -> no appropriate variables found in Fraction(Polynomial(Integer)) -> no appropriate variables found in Fraction(Polynomial(Integer))
Modemaps from Associated Packages no modemaps
Remaining General Modemaps [1] Fraction(Polynomial(D3)) -> List(Symbol) from RationalFunction( D3) if D3 has INTDOM [2] D -> List(D4) from D if D has PSETCAT(D2,D3,D4,D5) and D2 has RING and D3 has OAMONS and D4 has ORDSET and D5 has RPOLCAT(D2,D3,D4) [3] D -> List(D4) from D if D has PSCAT(D2,D3,D4) and D2 has RING and D3 has OAMON and D4 has ORDSET [4] D -> List(D4) from D if D has POLYCAT(D2,D3,D4) and D2 has RING and D3 has OAMONS and D4 has ORDSET [5] D -> List(Symbol) from D if D has FS(D2) and D2 has COMPAR
[1] signature: FRAC(POLY(INT)) -> LIST(SYMBOL) implemented: slot (List (Symbol))(Fraction (Polynomial (Integer))) from RF(INT) [2] signature: EXPR(INT) -> LIST(SYMBOL) implemented: slot (List (Symbol))$ from EXPR(INT) [3] signature: POLY(INT) -> LIST(SYMBOL) implemented: slot (List (Symbol))$ from POLY(INT)

\label{eq3}\left[ x \right](3)
Type: List(Symbol)

Here, variables comes from RF. Another way to watch Axiom looking for functions is )lisp (setq |$monitorNewWorld| t), but I don't understand its output too well. More possibilities are discussed in the file DeveloperNotes.dvi in axiom/mnt/linux/doc/.

Given that variables comes from UP, we still don't know where it is actually coded. In fact, there is no code for variables in UP. So, where does Axiom look next? We can find out about this using

asq -cc UP

which tells us, that the constructorcategory of UP is UPOLYC. Et voilĂ :

    )abbrev category UPOLYC UnivariatePolynomialCategory
    ...
    UnivariatePolynomialCategory(R:Ring): Category ==
      add
    ...
        variables(p) ==
          zero? p or zero?(degree p) => []
          [create()]

It also helps to look at the modeline of variables, which we can find out using ')sh UP':

    )sh UP
     UnivariatePolynomial(x: Symbol,R: Ring)  is a domain constructor
     Abbreviation for UnivariatePolynomial is UP 
     This constructor is exposed in this frame.
     Issue )edit /home/rubey/axiom/mnt/linux/../../src/algebra/UP.spad to see algebra source code for UP 

    ------------------------------- Operations --------------------------------
    ...
     variables : % -> List SingletonAsOrderedSet
    ...

SingletonAsOrderedSet? is a domain which consists of the single element "?"! Hence, we have reduced the problem of fixing the bug to a design issue.