🌐 AI搜索 & 代理 主页
Skip to content

Conversation

@ahbnr
Copy link
Contributor

@ahbnr ahbnr commented Jan 23, 2020

This branch implements a new type Any at the top of the type hierarchy
that is

T ≤ Any ∧ Any ≤ Any
  for all classes, interfaces and data types T
  where ≤ is the subtyping relation.

I needed this Any type for my thesis, where I implemented user-defined
schedulers based on Register Automata which stored futures in register fields.
I required these registers to be able to store any future and thus they had to be
of the type Fut<Any>.

@Edkamb asked me now to create a pull request for the Any type feature, so here
it is :).

However, during my implementation of Any, I focused on getting it to work for my
use-case, therefore there are still some issues which might need to be resolved
before merging:

  • 1. Edit: The issues stated in this section have now been resolved by adding a data Any; declaration to the stdlib, see the comments below this post.

    I did not add a type declaration for Any in the stdlib, since there is no
    syntax for it.
    This leads for example to some unsightly hacks during lookups, like this
    one in src/main/java/org/abs_models/frontend/typechecker/TypeResolution.jrag:

    syn lazy Decl Model.lookup(KindedName name) {
        if (name.getName().equals("Any")) { // <----
            return superDecl;
        }
    
        for (CompilationUnit u : getCompilationUnits()) {
            for (ModuleDecl d : u.getModuleDecls()) {
                Decl decl = d.lookup(name);
                if (!decl.equals(unknownDecl))
                    return decl;
            }    			
        }
        return unknownDecl;
    }
    

    (See also the other remaining TODOs within the changed files)

    One possibility of resolving this would be to add a built-in
    CompililationUnit to every compilation process which contains the
    AnyTypeDecl, similar to how the stdlib is added.
    I already implemented this with a few related changes in a second branch
    https://github.com/ahbnr/abstools/tree/commonSupertype_cleanup, see for example
    org.abs_models.frontend.parser.Main::getBuiltinUnit and the uses of that
    function.

    However, there is still a bug, which causes compilation to fail when
    programmatically adding AnyTypeDecl to a list of declarations in
    org.abs_models.frontend.parser.Main::getBuiltinUnit which I could not
    investigate yet.
    Strangely enough, this bug appears for me only when executing tests,
    not when directly compiling files.

  • 2. Any was useful to me, since it allowed me to compare a Fut<Any> register
    to any Fut<T> value (equality comparison), which worked for me with the Erlang
    backend.
    However, I'm not quite sure, how the backends (should) handle comparisons
    across types, for example:

    {
      Any x = 42.0;
      Bool y = False;
    
      Bool z = x == y; // <- what is the semantics of this comparison? What do the backends do?
    }
    

    So this issue probably needs to be discussed / the backends be checked how
    this is handled.

I added a few tests for Any in org.abs_models.backend.common.AnyTests and
in org.abs_models.frontend.typesystem.AnyTypeTests.

@rudi
Copy link
Member

rudi commented Jan 23, 2020

You can add a type declaration into the standard library even when there's no constructors; we do this for strings, numbers etc. data Any; gives you a type, and you will be able to remove a lot of special cases that you discuss above.

The previous implementation of Any required implementation of a lot of
logic for special cases. This reimplementation builds Any upon the
DataTypeType class and therefore a lot of the code for these special
cases could be removed.
@ahbnr
Copy link
Contributor Author

ahbnr commented Jan 24, 2020

You can add a type declaration into the standard library even when there's no constructors; we do this for strings, numbers etc. data Any; gives you a type, and you will be able to remove a lot of special cases that you discuss above.

Thank you for that hint. My latest commit now reimplements Any using a "data Any;" declaration and I was able to remove the special cases. I also added some additional tests.

As a sanity check, before continueing with the pull request, I would like to first merge back this reimplementation into my thesis project and check if everything still works. I think I can do this on monday.

@rudi
Copy link
Member

rudi commented Jan 26, 2020

Re your point 2, we currently have not only equality comparison but also ordering (less-than) in ABS -- see https://abs-models.org/manual/#sec:pure-expressions, subsection "Semantics of Comparison Operators".

With Any we can now compare values of different type, so we'll need an ordering relation between them. We can do the same thing as Erlang and just define such a relation (see http://erlang.org/doc/reference_manual/expressions.html#term-comparisons).

I anticipate the next thing after Any will be demand for downcasting (we have this for object references, with the implements and as expressions; see the manual), so any run-time type info needed for comparisons between values of different types could probably be used for that as well.

@ahbnr
Copy link
Contributor Author

ahbnr commented Jan 27, 2020

I anticipate the next thing after Any will be demand for downcasting (we have this for object references, with the implements and as expressions; see the manual), so any run-time type info needed for comparisons between values of different types could probably be used for that as well.

Hmm, if possible I would like to try to avoid adding explicit additional run-time type info to values, since then we would need to adapt most of the erlang backend to be compatible with the new data format, if I'm not mistaken.

Instead, I would try to infer the type from the current representation as cmp:lt (frontend/src/main/resources/erlang/absmodel/src/cmp.erl) seems to be doing already.
For the Java backend, instanceof checks could probably be used.

By the way, by how many/which backends should the Any type ideally be supported for now? Would it be sufficient to implement comparisons for Erlang?

With Any we can now compare values of different type, so we'll need an ordering relation between them. We can do the same thing as Erlang and just define such a relation (see http://erlang.org/doc/reference_manual/expressions.html#term-comparisons).

My use case for comparisons across types was restricted to equality comparisons of future references (see first post). Should we implement a less-than hierarchy like Erlang without knowing whether someone will use it in the near future? We could also define the result of all comparisons across types to be false, but allow comparisons of references and keep the conversion of numbers. This would probably result in implementing fewer special cases. But I'm also not sure, whether this would make the language "unintuitive", if there are incomparable elements a, b which satisfy !(a < b || b < a || a == b).

What do you think?

@rudi
Copy link
Member

rudi commented Feb 12, 2020

By the way, by how many/which backends should the Any type ideally be supported for now? Would it be sufficient to implement comparisons for Erlang?

Erlang is sufficient, yes.

@rudi
Copy link
Member

rudi commented Feb 12, 2020

With Any we can now compare values of different type, so we'll need an ordering relation between them. We can do the same thing as Erlang and just define such a relation (see http://erlang.org/doc/reference_manual/expressions.html#term-comparisons).

My use case for comparisons across types was restricted to equality comparisons of future references (see first post).

I learned through experience that adding a feature specialized to my own use case leads to unhappy users, who reasonably expect generality and orthogonality of features. That's the price of working on a tool with users that I don't personally know. (The reward, of course, is also working on a tool with users that I don't personally know.)

Should we implement a less-than hierarchy like Erlang without knowing whether someone will use it in the near future?

A medium-term goal for me is to redefine sets and maps to use red-black-trees or similar; in that case we have to have an ordering relation. This would mean we couldn't have Set<Any> ...

We should have an arbitrary ordering, e.g., future < reference < string < number < user-defined datatype, and compare user-defined datatypes similar to https://abs-models.org/manual/#sec:pure-expressions, subsection "Semantics of Comparison Operators" (where we describe how we compare terms with different constructors of the same user-defined datatype). In erlang, we would need to add the name of the datatype to values, or add a constructor -> datatype name mapping (constructor names are already contained in values, since we use them for pattern matching).

Anyway, I could have a look at implementing this if you agree that the semantics are basically sane.

@ahbnr
Copy link
Contributor Author

ahbnr commented Feb 20, 2020

You are right that adding a new type which does not support the less-than operation is probably a bad idea since it would create a special case for the users and the language, as it is the only type which does not support it.

Also, just defining the result of a less-than comparison of different types to be always False is also more confusing than an arbitrary ordering, since it would create a new kind of values where !(a < b || b < a || a == b) as I mentioned above.

As we discussed in Gitter, quite a lot of type information can already be extracted from the runtime representation. However, there are some cases where explicit type annotations will be required. For example, for empty lists we can't derive the type of the elements it stores at runtime:

{
   List<Float> l1 = Nil;
   List<Bool> l2 = Nil;
   List<Any> ll1 = l1;
   List<Any> ll2 = l2;

   Bool x = ll1 == ll2; // Should this be true or false?
}

Anyway, I could have a look at implementing this if you agree that the semantics are basically sane.

I don't want to increase your workload due to an issue I caused. So if we are not in a hurry, I could also look into implementing this. However, I'm quite busy for the next few weeks and will probably only be able to pick this up again in the middle of March : /

@rudi
Copy link
Member

rudi commented Feb 20, 2020

There's also always the possibility of restricting the less-than operator to numbers and strings. We would lose the possibility of generalized sorting and container implementations, but gain implementation efficiency. If I remember correctly e.g. Reiner was in favor of eliminating the general less-than operator, but not enough so to make a strong case for it.

Please do keep reminding me about this issue; I would not want to be a bottleneck for developing ABS.

If this issue is still open at the ABS workshop in Torino, I will bring it up then.

@rudi
Copy link
Member

rudi commented Feb 20, 2020

As we discussed in Gitter, quite a lot of type information can already be extracted from the runtime representation. However, there are some cases where explicit type annotations will be required. For example, for empty lists we can't derive the type of the elements it stores at runtime:

{
   List<Float> l1 = Nil;
   List<Bool> l2 = Nil;
   List<Any> ll1 = l1;
   List<Any> ll2 = l2;

   Bool x = ll1 == ll2; // Should this be true or false?
}

I'm not sure if there's a more sophisticated argument to be made here, but I'd make a case that the code above is equivalent to the following, which is trivially true:

{
   List<Any> ll1 = Nil;
   List<Any> ll2 = Nil;
   Bool x = ll1 == ll2; // true
}

@rudi rudi marked this pull request as draft March 11, 2022 13:58
@rudi rudi requested review from Edkamb and rudi March 11, 2022 13:59
@ahbnr
Copy link
Contributor Author

ahbnr commented Mar 21, 2022

I created a new branch and opened a new pull request for introducing the restricted version of Any that we discussed: #309.

This is because I based that new version on the current state of master and I want to preserve the old branch for reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants