"Bill Page" <[EMAIL PROTECTED]> writes:

| On Thu, May 15, 2008 at 6:02 AM, Gabriel Dos Reis wrote:
| > Ralf Hemmecke writes:
| >
| > | > If the scope of 'x' is intended to be global, then the type of 'x'
| > | > must be a Union.
| > | >     x:Union(Integer,Float)
| > | >     if cond then
| > | >         x := 1
| > | >     else
| > | >         x := 2.3
| > |
| > | Of course that cannot work. What function pointer for
| > | multiplication should the compiler put in for the following
| > |
| > | x := x*x
| > |
| > | ? Union does not export a multiplication.
| >
| > True, and given that why
| >
| >   x := x * x
| >
| > would have to be valid at all?
| >
| 
| ??? No, it is not true.

I disagree.  See below.

| I guess you didn't try it before you wrote ... :-)

Did not try what exactly?

| The code example I provided works as advertised in both the
| interpreter and the SPAD compiler:

Again, in this discussion my focus is on the compiler, because it is
the one that presents the most challenges: How to generate code for
dependent types (that depend not only values but on data flow).  The
interpreter is a `toy', compared to the rest.  Mostly because, the
interpreter does a small-step semantics, therefore always holds the
most accurate type.  The compiler must do a sound abstract
interpretation of the code where it has no access to the actual data
and control flow.

| (1) -> x:Union(Integer,Float)
|                                                    Type: Void
| 
| (2) -> if 0<1 then x:=1 else x:=2.3
| 
|    (2)  1
|                                                    Type: Union(Integer,...)
| 
| (3) -> x := x*x
| 
|    (3)  1
|                                                    Type: Union(Integer,...)
| 
| (4) -> if 1<0 then x:=1 else x:=2.3
| 
|    (4)  2.3
|                                                   Type: Union(Float,...)
| 
| (5) -> x := x*x
| 
|    (5)  5.29
|                                                   Type: Union(Float,...)

For the interpreter, it is not a problem because it always holds the
most accurate type, as displayed i the `Type:' annotation.

I keep your interpreter code just to show that you did NOT present the
same code to the compiler.

| ---------
| 
| For the compiler see:
| 
| http://axiom-wiki.newsynthesis.org/SandBoxLexicalScope#bottom
| 
| \begin{spad}
| )abbrev domain BBB Bbb
| Bbb: with
|     foo: Integer -> Integer
|   == add
|     foo(a: Integer): Integer ==
|      x:Union(Integer,Float)
|      if a>0 then
|          x := 1
|      else
|          x := 2.3
|      x case Integer => (x*x)::Integer
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Here, you are *manually inserting* the right coercion.  This is not
the same thing you did in the interpreter case.  This is precisely
where I was commenting.  So, ether you do the same thing in the
interpreter and the compiler or you compare oranges to apples.  If
you're going to manually insert the right coercions, you may just as
well declare the variable explicitly as being a Union.

You were wondering about `autoCoerce' in another message.  They are
exactly for this case.  Let me explain.

When you have a union, usualy you have to do a `case' to take a
branch, such as above 

   x case Integer => (x*x)::Integer

this is equivalent to 

   if  x case Integer then return (x*x)::Integer
   else  ...

Now, the compiler keeps track of control flow (see compIf), and when it is
in the success branch it knows that that `the Integer branch' is
taken -- the environment is augmented with a `condition' property
that records the `case expression -- and if you use `x' in that branch
where an Integer is used, it will call autoCoerce with Integer as
target -- see coerceExtraHard() -- which will insert by right coercion
by simple modemap selection.  Notice that I extended this mechanism to
user defined `case' operator back then when I introduced the Syntax
domain.  When the compiler is in the `else' branch, it compiles the
code in the `inverse environment' -- see compBoolean. The inverse
environment is computed by removing all `success' tags from the success
environment.  In the specific case where your union contains 
only two branches you have the impression that you don't have to say
anything in the else branch, precisely because there remains only one
`autoCoerce' for use.  If you have more branches you will have to 
manually chose the `right coercions'.

|      wholePart(x*x)
| \end{spad}
| 
| \begin{axiom}
| foo(0)
| foo(1)
| \end{axiom}
| 
| This outputs  5 and 1 respectively. Even the compiler is smart enough
| to select the right * operation given enough context.

you manually inserted the coercions, that is a different ball game.

Try:

)abbrev package BILLPAGE BillPageUnion
BillPageUnion(): Public == Private where
  Public ==> with
    foo: () -> Void
  Private ==> add
    makeU(): Union(Integer,Float) ==
     even? random()$Integer => 1
     3.14

    foo() ==
      x: Union(Integer,Float) := makeU()
      y: Union(Integer,Float) := makeU()
      x ** y

-- Gaby

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
open-axiom-devel mailing list
open-axiom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/open-axiom-devel

Reply via email to