Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflection #57

Open
SeanTAllen opened this issue Oct 22, 2016 · 6 comments
Open

Reflection #57

SeanTAllen opened this issue Oct 22, 2016 · 6 comments

Comments

@SeanTAllen
Copy link
Member

This is the new home of the ponyc issue 87.

The reflection API should be mirror-based and capabilities-secure.

If you'd like to take on writing this RFC, we'd welcome working with you.

@mfelsche
Copy link
Contributor

One humble suggestion for sparking the discussion:

To ease the step to getting a reflection API up and running for pony, maybe it is worth to get things started with a really basic version that is only able to output the type name of a class.

It might be implemented as some kind of Type class/primitive that represents the type of an object as the compiler sees it.

An example API

// example with type method generated for every class/primitive
let myStringRef: (Stringable & ByteSeq) = "abc"
let type: Type = myStringRef.type()
let typeName = type.name() // "String"

// example with Reflection primitive
let myRefWithTypeParams: Array[String] = ["abc"; "def"]
let type: Type = Reflection.type(myRefWithTypeParams)
let typeName = type.name() // "Array[String]"

Getting the type from an object reference might not need to involve any capability checking or Auth as long as the type is as simple as outlined above.

Such a Type could also provide access the Types of the traits of an object. I am not sure if it possible to access implemented interfaces, but it sure would be a nice feature of a Type class.

trait Type
   fun name(): String
   fun traits(): Seq[Type]
   fun interfaces(): Seq[Type]

Given that this is very barebones, i think it is necessary to make sure that its design doesn't contradict with the vision of the full reflection API. So it will be easy to just extend the given types and methods without breaking changes if possible.

@niclash
Copy link

niclash commented Aug 28, 2019

I think that the first step is an Introspection API, rather than the full-fledged Reflection system found in Java and elsewhere, where you can modify values willy-nilly which will violate compiler type/data-race safety. And perhaps reading values are also left out for that reason, but calling behaviors and constructors should be ok (I think).

IF (this part is unclear to me atm) there is only a "compile all from source" option, i.e. no libraries, then the compiler can determine (by encountering call to Introspection) whether the Introspection Meta-info should be included in the binary or not.

I would like to propose a little bit more of "barebones" than @mfelsche above. Since I am not at all proficient in Pony yet, I am sure there are many things that I have misunderstood, so please bear with me, but I think it is a reasonable starting point from someone who has extensive experience with reflection in Java (all the way back to when Reflection API was introduced in Java 1.1 (1997))

I don't think we should burden all types with type() function, but simply have a type_of() in the Introspection API, since more often than not, this is not used.

I think(!) the stuff below is not inflicting complications on the type system guarantees, as only behaviors can be invoked and constructors to be called.


trait Introspection
    fun package(name:String): Package val
    fun type_of(object: (Object | None) ): Type val

trait Package
    fun name(): String val
    fun members(): Seq[Type] val

trait Type
    fun package(): Seq[Package] val
    fun name(): String val
    fun traits(): Seq[Type] val
    fun declared_interfaces(): Seq[Type] val
    fun implements_interface(intface: Type): Bool val
    fun is_private(): Bool val
    fun is_actor(): Bool val
    fun is_class(): Bool val
    fun is_primitive(): Bool val
    fun is_type(): Bool val
    fun is_struct(): Bool val
    fun is_array(): Bool val
    fun is_union(): Bool val
    fun is_intersection(): Bool val
    fun fields(): Seq[Alias] val
    fun functions(): Seq[Function] val
    fun constructors(): Seq[Constructor] val

trait Actor is Type
    fun behaviors(): Seq[Behavior] val

trait UnionType is Type
    fun members(): Seq[Type] val

trait IntersectionType is Type
    fun members(): Seq[Type] val

trait Alias
    fun name(): String val
    fun capability(): Capability val
    fun is_private(): Bool val

trait Tuple
    fun aliases(): Seq[Alias] val

trait Function
    fun name(): String val
    fun capability(): Capability val
    fun parameters(): Seq[(Alias | Tuple | Lambda)] val   // can tuples be passed as arguments?
    fun returns(): (Alias | Tuple | Lambda) val
    fun is_private(): Bool val

trait Lambda is Function

trait Behavior is Function 
    fun invoke( actor:Object tag, args: Array[Object] )

trait Constructor[T:Type] is Function 
    fun apply( args: Array[Object] ) : T ref^

type Capability is ( Iso | Val | Ref | Box | Trn | Tag )

primitive Iso 
primitive Val 
primitive Ref 
primitive Box 
primitive Trn 
primitive Tag

@SeanTAllen
Copy link
Member Author

I don't much like the idea of having traits/interfaces that you have to opt into. I'm also not a fan of segmenting off a large chunk of namespacing like name where no class can have name as a method because it would conflict with reflection/introspection.

It would result in a lot of code breakage.

On a user API side, I'd rather see some combination of primitives that can be passed Pony objects like instances of a class, actor, etc and extract information from it via something that I think would be using a c-api to hooked into information generated at compile time.

@niclash
Copy link

niclash commented Aug 28, 2019 via email

@SeanTAllen
Copy link
Member Author

@niclash what would implement these traits that you propose?

Perhaps I was mislead by your usage of trait in your example and that wasn't what you were intending.

@niclash
Copy link

niclash commented Aug 28, 2019 via email

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

No branches or pull requests

3 participants