-
Notifications
You must be signed in to change notification settings - Fork 11
feat: Declare WASM modules in guppy #942
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #942 +/- ##
==========================================
- Coverage 92.85% 92.43% -0.43%
==========================================
Files 85 88 +3
Lines 9901 10180 +279
==========================================
+ Hits 9194 9410 +216
- Misses 707 770 +63 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Craig! I left a bunch of nits and suggestions while looking through the code, but my main points are:
- I'd prefer to use an
OpaqueType
instead of addingWasmModuleType
to the core type system - Instead of
CustomFunctionDef
s , I think it would be cleaner to add aWasmFunctionDef
that takes care of checking the signature instead of doing it at the call-site. You could follow the pattern inguppylang.definition.function
for how to set it up and mostly copy the code you already have from theCustomCallChecker
s andCustomCallCompiler
s.
Also, it would be good to have some tests for the new error messages you added
from guppylang.tys.ty import Type | ||
|
||
|
||
class WasmError(Error): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class WasmError(Error): | |
@dataclass(frozen=True) | |
class WasmError(Error): |
|
||
|
||
@dataclass(frozen=True) | ||
class WasmTypeConversionError(Error): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be in errors/wasm.py
?
def wasm_module( | ||
self, filename: str, filehash: int | ||
) -> Decorator[PyClass, GuppyDefinition]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that your decorator doesn't work with explicit modules.
I think that's fine as long as we merge #983 first
case FuncInput(ty=ty, flags=InputFlags.Inout) if isinstance( | ||
ty, WasmModuleType | ||
): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
case FuncInput(ty=ty, flags=InputFlags.Inout) if isinstance( | |
ty, WasmModuleType | |
): | |
case FuncInput(ty=WasmModuleType(), flags=InputFlags.Inout): |
case FuncInput(ty=ty): | ||
raise GuppyError(FirstArgNotModule(self.node, ty)) | ||
for inp in self.func.ty.inputs[1:]: | ||
assert isinstance(inp, FuncInput) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assert seems unnecessary?
class ConstStringArg(ConstArg): | ||
def to_hugr(self) -> ht.TypeArg: | ||
match self.const: | ||
case ConstValue(value=v, ty=ty) if is_string_type(ty): | ||
assert isinstance(v, str) | ||
return ht.StringArg(v) | ||
case _: | ||
return super().to_hugr() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a new subclass instead of adding this logic to ConstArg.to_hugr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes I meant to highlight this - adding the logic to ConstArg.to_hugr
makes sense, but introduces a cyclic dependency guppylang.tys.arg.py <-> guppylang.tys.builtin.py
@@ -150,6 +151,10 @@ def _visit_ConstArg(self, arg: ConstArg, inside_row: bool) -> str: | |||
def _visit_ConstValue(self, c: ConstValue, inside_row: bool) -> str: | |||
return str(c.value) | |||
|
|||
@_visit.register | |||
def _visit_WasmModuleType(self, w: WasmModuleType, inside_row: bool) -> str: | |||
return f"WasmModuleType(defn={w.defn!s})" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the type that is printed to users. It should be the name that the user gave to the class defining the module
ty = wasm().get_type("context") | ||
return ty.instantiate([]) | ||
|
||
# TODO: I don't know what to write here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you wrote is valid since WasmModuleType
contains no nested types 👍
@@ -663,6 +664,30 @@ def transform(self, transformer: Transformer) -> "Type": | |||
) | |||
|
|||
|
|||
@dataclass(frozen=True) | |||
class WasmModuleType(TypeBase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like the idea of adding wasm to the core type system.
Especially since you're just wrapping a definition and no other logic, why not use an OpaqueType
? Everywhere you check for a WasmModuleType
, you could just check that it's opaque and the definition matches?
@@ -82,6 +82,9 @@ class GuppyModule: | |||
# Storage for source code that has been read by the compiler | |||
_sources: SourceMap | |||
|
|||
# Live WASM contexts | |||
_next_wasm_context: int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also do
_wasm_ids = itertools.count()
Then, you can just do next(self._wasm_ids)
and the counter goes up automatically
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or even better, move the counter to WasmModuleDef
instead of sticking it to the module
TODO:
(this is required for generic size arrays to work)
n
contexts