From 8d09aea1f70db5847bfa084ddcfa7e7253be774a Mon Sep 17 00:00:00 2001 From: pca006132 Date: Tue, 19 Jan 2021 15:35:11 +0800 Subject: [PATCH] recent changes --- README.md | 60 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 0fe16ba..7ca92ec 100644 --- a/README.md +++ b/README.md @@ -6,34 +6,18 @@ A toy implementation is in [`toy-impl`](./toy-impl), requires python 3.9. ## Referencing Python Variables -The kernel is allowed to read 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) -* Unbounded identifiers would be considered as Python variables, no object is - allowed, only primitive types and tuple/list of allowed types are allowed. - (not sure how to express the recursive concept neatly in English...) -* The value would be evaluated at compile time, subsequent modification - in the host would not be known by the kernel. -* Modification of global variable from within the kernel would be considered as - error. -* Calling non-RPC host function would be considered as an error. (RPC functions - must be annotated.) +Only primitive types and tuple/list of primitive types are allowed. -Example code that would be disallowed: -```py -from artiq.experiment import * -counter = 0 -def get_id(): - counter += 1 - return counter +The value would be substituted at compile time, subsequent modification in the +host would not be known by the kernel. -class Foo(EnvExperiment): - @kernel - def run(self): - param = get_id() - # do something... - result = param - return result -``` +Modification in kernel code to the global variables is not allowed. ## Class and Functions * Class fields must be annotated: @@ -55,8 +39,14 @@ class Foo(EnvExperiment): 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, and that is a potential source of - confusion. + 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? ## Built-in Types * Primitive types include: @@ -85,7 +75,7 @@ class Foo(EnvExperiment): i = 0 a = t[i] ``` - * `range` (over numerical types) + * `range` (over numerical types) (not sure if this is really useful) ### Numerical Types * All binary operations expect the values to have the same type, no implicit @@ -113,9 +103,9 @@ class Foo(EnvExperiment): ``` * Type variables can only be used in functions/methods, but not in classes. -* Type variable can be limited to a fixed set of types. A shorthand for one-time - type variable limited to a fixed set of types is [union type & optional type](https://docs.python.org/3/library/typing.html#typing.Union). - e.g. `def run(self, a: Union[int, str])` + (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. @@ -133,7 +123,8 @@ class Foo(EnvExperiment): * Generics are instantiated at compile time, all the type checks like `type(x) == int` would be evaluated as constants. Type checks are not allowed in area outside generics. -* Type variable and union cannot occur alone in the result type. +* Type variable cannot occur alone in the result type, i.e. must be bound to the + input parameters. ## Dynamic Dispatch Type annotations are invariant, so subtype (derived types) cannot be used @@ -153,7 +144,7 @@ def bar(x: list[Base]) -> int: sum += v.foo() return sum -# incorrect, the type signature of the list is `list[virtual[Base]]` +# incorrect, this list cannot be typed (inhomogeneous) bar([Base(), Derived()]) ``` @@ -168,6 +159,7 @@ 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 @@ -176,8 +168,6 @@ def bar2(x: list[virtual[Base]]) -> int: for v in x: sum += v.foo() return sum -# correct -bar([Base(), Derived()]) ```