add back documentation about virtual types #22
58
README.md
58
README.md
|
@ -181,6 +181,10 @@ class Foo(EnvExperiment):
|
||||||
in area outside generics.
|
in area outside generics.
|
||||||
* Type variable cannot occur alone in the result type, i.e. must be bound to the
|
* Type variable cannot occur alone in the result type, i.e. must be bound to the
|
||||||
input parameters.
|
input parameters.
|
||||||
|
* Polymorphic methods (with type variables in the type signature) must be
|
||||||
|
annotated with `@final`. This is because we need to know where does the method
|
||||||
|
come from when we do monomorphization, which we don't know for virtual
|
||||||
|
methods.
|
||||||
|
|
||||||
## For loop unrolling (#12)
|
## For loop unrolling (#12)
|
||||||
A pseudocomment can be used for unrolling for loops that iterates a fixed amount
|
A pseudocomment can be used for unrolling for loops that iterates a fixed amount
|
||||||
|
@ -193,6 +197,60 @@ for p in params:
|
||||||
print(p)
|
print(p)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Dynamic Dispatch
|
||||||
|
Type annotations are invariant, so subtype (derived types) cannot be used
|
||||||
|
when the base type is expected. Example:
|
||||||
|
```python
|
||||||
|
class Base:
|
||||||
|
def foo(self) -> int:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
class Derived(Base):
|
||||||
|
def foo(self) -> int:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def bar(x: list[Base]) -> int:
|
||||||
|
sum = 0
|
||||||
|
for v in x:
|
||||||
|
sum += v.foo()
|
||||||
|
return sum
|
||||||
|
|
||||||
|
# incorrect, this list cannot be typed (inhomogeneous)
|
||||||
|
bar([Base(), Derived()])
|
||||||
|
```
|
||||||
|
|
||||||
|
Dynamic dispatch is supported, but requires explicit annotation, similar to
|
||||||
|
[trait object](https://doc.rust-lang.org/book/ch17-02-trait-objects.html) in rust.
|
||||||
|
`virtual[T]` is the type for `T` and its subtypes(derived types).
|
||||||
|
|
||||||
|
This is mainly for performance consideration, as virtual method table that is
|
||||||
|
required for dynamic dispatch would penalize performance, and prohibits function
|
||||||
|
inlining etc. Note that type variables cannot be used inside `virtual[...]`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```py
|
||||||
|
def bar2(x: list[virtual[Base]]) -> int:
|
||||||
|
sum = 0
|
||||||
|
for v in x:
|
||||||
|
sum += v.foo()
|
||||||
|
return sum
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax for casting virtual objects is `virtual(obj, T)`, which casts an
|
||||||
|
object of type `T1/virtual[T1]` to `virtual[T]` where `T1 <: T` (T1 is a subtype
|
||||||
|
of T).
|
||||||
|
|
||||||
|
The compiler may be able to infer the type cast. In that case, the cast
|
||||||
|
is not required if `obj` is already of type `virtual[T1]`, or the user can write
|
||||||
|
the cast as `virtual(obj)` and the compiler would infer the type `T`
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
Methods would be automatically overriden, the type signature including parameter
|
||||||
|
names and order must be exactly the same.
|
||||||
|
|
||||||
|
Defining a method which was marked as final in the super class would be
|
||||||
|
considered as an error.
|
||||||
|
|
||||||
## Lifetime
|
## Lifetime
|
||||||
Probably need more discussions...
|
Probably need more discussions...
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue