From d82edd27536c931da3bd2ad230223bccd412622f Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sun, 11 Apr 2021 23:29:43 +0800 Subject: [PATCH 1/5] updated according to discussions - Updated details related to class instance variables. - Rewrote section about referencing host variables from kernel. - Updated limitation regarding default parameter, function pointers and integer type. - Removed section about dynamic dispatch, maybe deal with this later. --- README.md | 126 ++++++++++++++++++------------------------------------ 1 file changed, 41 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index dd80ded..a0ffdda 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,22 @@ Specification and discussions about language design. A toy implementation is in [`toy-impl`](./toy-impl), requires python 3.9. -## Referencing Python Variables -The kernel is allowed to read host Python variables, but has to specify with -`global` before referencing them. This is to simplify and speed-up -implementation, and also warn the user about the variable being global. (prevent -calling the interpreter many times during compilation if there are many -references to host variables) +## Referencing Host Variables from Kernel +Host variable to be accessed must be declared as `global` in the kernel +function. This is to simplify and speed-up implementation, and also warn the +user about the variable being global. (prevent calling the interpreter many +times during compilation if there are many references to host variables) -Only primitive types and tuple/list of primitive types are allowed. +Kernel cannot modify host variables, this would be checked by the compiler. +Value that can be observed by the kernel would be frozen once the kernel has +been compiled, subsequence modification within the host would not affect the +kernel. -The value would be substituted at compile time, subsequent modification in the -host would not be known by the kernel. - -Modification in kernel code to the global variables is not allowed. +Only types supported in the kernel can be referenced. ## Class and Functions -* Class fields must be annotated: - ```py +* Instance variables must be annotated: (Issue #1) + ```python class Foo: a: int b: int @@ -29,24 +28,24 @@ Modification in kernel code to the global variables is not allowed. self.a = a self.b = b ``` +* Three types of instance variables: (Issue #5) + * Host only variables: Do not add type annotation for it in the class. + * Kernel Invariants: Immutable in the kernel and in the host while the kernel + is executing. Type: `KernelInvariant(T)`. The types must be immutable. + (use tuple instead of list in the host, but the type annotation should still + be list?) + * Normal Variables: The host can only assign to them in the `__init__` + function. Not accessible afterwards. * Functions require full type signature, including type annotation to every parameter and return type. - ```py + ```python def add(a: int, b: int) -> int: return a + b ``` -* No implicit coercion, require implicit cast. Integers are int32 by default, - floating point numbers are double by default. * RPCs: optional parameter type signature, require return type signature. -* Function default parameters are not allowed, as changes to the default value - would not be kept across kernel calls, which is a potential source of - confusion. (maybe we can allow primitive default types?) -* Cannot construct objects within kernel code. - -Questions: -* Can we construct objects within kernel code? -* Should we support function pointers? What about subtyping with function - pointers, and generic types? +* Function default parameters must be immutable. +* Function pointers are supported, and lambda expression is not supported + currently. (maybe support lambda after implementing type inference?) ## Built-in Types * Primitive types include: @@ -57,14 +56,14 @@ Questions: * `uint32` * `uint64` * `float` - * `str` (note: fixed length, provide builtin methods?) - * `bytes` (a list of `byte`, but with more convenient syntax) + * `str` + * `bytes` * Collections include: * `list`: homogeneous (elements must be of the same type) fixed-size (no append) list. - * `tuple`: inhomogeneous fixed-size list, only pattern - matching (e.g. `a, b, c = (1, True, 1.2)`) and constant indexing - is supported: + * `tuple`: inhomogeneous immutable list, only pattern + matching (e.g. `a, b, c = (1, True, 1.2)`) and constant indexing is + supported: ``` t = (1, True) # OK @@ -75,23 +74,25 @@ Questions: i = 0 a = t[i] ``` - * `range` (over numerical types) (not sure if this is really useful) + * `range` (over numerical types) ### Numerical Types -* All binary operations expect the values to have the same type, no implicit - coercion would be performed, explicit casting is required. +* All binary operations expect the values to have the same type. * Casting can be done by `T(v)` where `T` is the target type, and `v` is the original value. Examples: `int64(123)` -* Constant integers are treated as `int32` by default. If the value cannot - be stored in `int32`, `uint64` would be used if the integer is non-negative, - and `int64` would be used it the integer is negative. +* Integers are treated as `int32` by default. Floating point numbers are double + by default. +* No implicit coercion, require implicit cast. + For integers that don't fit in int32, users should cast them to `int64` + explicitly, i.e. `int64(2147483648)`. If the compiler found that the integer + does not fit into int32, it would raise an error. (Issue #2) * Only `uint32`, `int32` (and range of them) can be used as index. ## Generics We use [type variable](https://docs.python.org/3/library/typing.html#typing.TypeVar) for denoting generics. Example: -```py +```python from typing import TypeVar T = TypeVar('T') @@ -102,16 +103,13 @@ class Foo(EnvExperiment): return a == b ``` -* Type variables can only be used in functions/methods, but not in classes. - (this can be relaxed, only allow those with type variables fully defined - from the constructor) * Type variable can be limited to a fixed set of types. * Type variables are invariant, same as the default in Python. We disallow covariant or contravariant. The compiler should mark as error if it encounters a type variable used in kernel that is declared covariant or contravariant. * Code region protected by a type check, such as `if type(x) == int:`, would treat `x` as `int`, similar to how [typescript type guard](https://www.typescripttutorial.net/typescript-tutorial/typescript-type-guards/) works. - ```py + ```python def add1(x: Union[int, bool]) -> int: if type(x) == int: # x is int @@ -131,48 +129,6 @@ Questions: * Would it be better to assert on the type variable directly instead of `type(x)` for type guards? -## Dynamic Dispatch -Type annotations are invariant, so subtype (derived types) cannot be used -when the base type is expected. Example: -```py -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. - -Type variables cannot be used inside `virtual[...]`, and type variables would not -range over `virtual[...]`. - -> Not sure what is the best syntax for `virtual[...]` - -Example: -```py -def bar2(x: list[virtual[Base]]) -> int: - sum = 0 - for v in x: - sum += v.foo() - return sum -``` - +## Lifetime +Probably need more discussions... From 30dd6a1ac1b0894bbcf46497531359e31ca31f91 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Sun, 11 Apr 2021 23:36:18 +0800 Subject: [PATCH 2/5] added kernel only class --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a0ffdda..dec672e 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,14 @@ Only types supported in the kernel can be referenced. does not fit into int32, it would raise an error. (Issue #2) * Only `uint32`, `int32` (and range of them) can be used as index. +### Kernel Only class +* Annotate the class with `@kernel`. +* Functions are all kernel only, including constructor. + +Questions: +* Should we also do `@portable`? +* Support inheritance and polymorphism? + ## Generics We use [type variable](https://docs.python.org/3/library/typing.html#typing.TypeVar) for denoting generics. From 284ab3324c52c2dba8f55d3d3ed804a75795372f Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 12 Apr 2021 19:58:29 +0800 Subject: [PATCH 3/5] modified according to comments --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dec672e..1570f31 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,25 @@ kernel. Only types supported in the kernel can be referenced. +Examples: +```python +FOO = 0 + +@kernel +def correct() -> int: + global FOO + return FOO + 1 + +@kernel +def fail_without_global() -> int: + return FOO + 2 + +@kernel +def fail_write() -> None: + FOO += 1 + +``` + ## Class and Functions * Instance variables must be annotated: (Issue #1) ```python @@ -31,7 +50,7 @@ Only types supported in the kernel can be referenced. * Three types of instance variables: (Issue #5) * Host only variables: Do not add type annotation for it in the class. * Kernel Invariants: Immutable in the kernel and in the host while the kernel - is executing. Type: `KernelInvariant(T)`. The types must be immutable. + is executing. Type: `KernelInvariant[T]`. The types must be immutable. (use tuple instead of list in the host, but the type annotation should still be list?) * Normal Variables: The host can only assign to them in the `__init__` @@ -47,6 +66,8 @@ Only types supported in the kernel can be referenced. * Function pointers are supported, and lambda expression is not supported currently. (maybe support lambda after implementing type inference?) + Its type is denoted by the typing library, e.g. `Call[[int32, int32], int32]`. + ## Built-in Types * Primitive types include: * `bool` From a034251c23e47ac7c948389bf9c228da6c380d06 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 12 Apr 2021 19:58:45 +0800 Subject: [PATCH 4/5] improved explanation for kernel only classes --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1570f31..c9ac79d 100644 --- a/README.md +++ b/README.md @@ -110,12 +110,13 @@ def fail_write() -> None: * Only `uint32`, `int32` (and range of them) can be used as index. ### Kernel Only class -* Annotate the class with `@kernel`. -* Functions are all kernel only, including constructor. - -Questions: -* Should we also do `@portable`? -* Support inheritance and polymorphism? +* Annotate the class with `@kernel`/`@portable`. +* The instance can be created from within kernel functions, or the host if it is + portable. It can be passed into kernels. +* All methods, including the constructor, are treated as kernel/portable + functions that would be compiled by the compiler, no RPC function is allowed. +* If the instance is passed into the kernel, the host is not allowed to access + the instance data. Access would raise exception. ## Generics We use [type variable](https://docs.python.org/3/library/typing.html#typing.TypeVar) for denoting generics. From 24a85c472eb92da1cea7b4eba11165c345f791c4 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 12 Apr 2021 20:16:26 +0800 Subject: [PATCH 5/5] updated type variable description --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index c9ac79d..ee9a147 100644 --- a/README.md +++ b/README.md @@ -154,11 +154,6 @@ class Foo(EnvExperiment): * Type variable cannot occur alone in the result type, i.e. must be bound to the input parameters. -Questions: -* Should we support things like optional type? (like the one in rust) -* Would it be better to assert on the type variable directly instead of - `type(x)` for type guards? - ## Lifetime Probably need more discussions...