-
Notifications
You must be signed in to change notification settings - Fork 18
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
Changes from all commits
426a5e6
2da0811
219e293
7361fe2
d5c570f
af7f7d8
95b1cb2
cc8aef1
caf37f4
c8a7b71
c6d66d8
fe23a6c
55805ee
8de275a
c0f70b9
07e1f62
9b3bf0b
d355b67
3f4bf50
46f6469
50986f7
061a6ba
b2aef12
5ed8479
e27d362
147a73a
4ff1525
8a0a188
88b5b0c
faadea6
84ebbdb
1d09e45
79beec5
7aebba1
3b584d3
9ea17ec
5b3f43d
e24e3f5
e677be2
3fafda6
9482b31
925c22d
8488e33
c65d4a0
277182c
c73ef71
3aa675f
cba859c
4565fb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| from dataclasses import dataclass | ||
| from typing import ClassVar | ||
|
|
||
| from guppylang.diagnostic import Error | ||
| from guppylang.tys.ty import Type | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class WasmError(Error): | ||
| title: ClassVar[str] = "WASM signature error" | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class FirstArgNotModule(WasmError): | ||
| span_label: ClassVar[str] = ( | ||
| "First argument to WASM function should be a reference to a WASM module." | ||
| " Found `{ty}` instead" | ||
| ) | ||
| ty: Type | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class UnWasmableType(WasmError): | ||
| span_label: ClassVar[str] = ( | ||
| "WASM function signature contained an unsupported type: `{ty}`" | ||
| ) | ||
| ty: Type | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class WasmTypeConversionError(Error): | ||
| title: ClassVar[str] = "Can't convert type to WASM" | ||
| span_label: ClassVar[str] = "`{thing}` cannot be converted to WASM" | ||
| ty: Type | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,7 +179,7 @@ class CustomFunctionDef(CompiledCallableDef): | |
| has_signature: Whether the function has a declared signature. | ||
| """ | ||
|
|
||
| defined_at: AstNode | ||
| defined_at: AstNode | None | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this change still needed?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is for the |
||
| ty: FunctionType | ||
| call_checker: "CustomCallChecker" | ||
| call_compiler: "CustomInoutCallCompiler" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| from guppylang.ast_util import AstNode | ||
| from guppylang.checker.errors.wasm import ( | ||
| FirstArgNotModule, | ||
| UnWasmableType, | ||
| ) | ||
| from guppylang.definition.custom import CustomFunctionDef, RawCustomFunctionDef | ||
| from guppylang.error import GuppyError | ||
| from guppylang.span import SourceMap | ||
| from guppylang.tys.builtin import wasm_module_info | ||
| from guppylang.tys.ty import ( | ||
| FuncInput, | ||
| FunctionType, | ||
| InputFlags, | ||
| NoneType, | ||
| NumericType, | ||
| TupleType, | ||
| Type, | ||
| ) | ||
|
|
||
| if TYPE_CHECKING: | ||
| from guppylang.checker.core import Globals | ||
|
|
||
|
|
||
| class RawWasmFunctionDef(RawCustomFunctionDef): | ||
| def sanitise_type(self, loc: AstNode | None, fun_ty: FunctionType) -> None: | ||
| # Place to highlight in error messages | ||
| match fun_ty.inputs[0]: | ||
| case FuncInput(ty=ty, flags=InputFlags.Inout) if wasm_module_info( | ||
| ty | ||
| ) is not None: | ||
| pass | ||
| case FuncInput(ty=ty): | ||
| raise GuppyError(FirstArgNotModule(loc, ty)) | ||
| for inp in fun_ty.inputs[1:]: | ||
| if not self.is_type_wasmable(inp.ty): | ||
| raise GuppyError(UnWasmableType(loc, inp.ty)) | ||
| if not self.is_type_wasmable(fun_ty.output): | ||
| match fun_ty.output: | ||
| case NoneType(): | ||
| pass | ||
| case _: | ||
| raise GuppyError(UnWasmableType(loc, fun_ty.output)) | ||
|
|
||
| def is_type_wasmable(self, ty: Type) -> bool: | ||
| match ty: | ||
| case NumericType(): | ||
| return True | ||
| case TupleType(element_types=tys): | ||
| return all(self.is_type_wasmable(ty) for ty in tys) | ||
|
|
||
| return False | ||
|
|
||
| def parse(self, globals: "Globals", sources: SourceMap) -> "CustomFunctionDef": | ||
| parsed = super().parse(globals, sources) | ||
| self.sanitise_type(parsed.defined_at, parsed.ty) | ||
| return parsed |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
| from guppylang.checker.expr_checker import ( | ||
| ExprChecker, | ||
| ExprSynthesizer, | ||
| check_call, | ||
| check_num_args, | ||
| check_type_against, | ||
| synthesize_call, | ||
|
|
@@ -557,3 +558,16 @@ def synthesize(self, args: list[ast.expr]) -> tuple[ast.expr, Type]: | |
| assert len(inst) == 0, "func_ty is not generic" | ||
| node = BarrierExpr(args=args, func_ty=func_ty) | ||
| return with_loc(self.node, node), ret_ty | ||
|
|
||
|
|
||
| class WasmCallChecker(CustomCallChecker): | ||
| def check(self, args: list[ast.expr], ty: Type) -> tuple[ast.expr, Subst]: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're skipping the |
||
| # Use default implementation from the expression checker | ||
| args, subst, inst = check_call(self.func.ty, args, ty, self.node, self.ctx) | ||
|
|
||
| return GlobalCall(def_id=self.func.id, args=args, type_args=inst), subst | ||
|
|
||
| def synthesize(self, args: list[ast.expr]) -> tuple[ast.expr, Type]: | ||
| # Use default implementation from the expression checker | ||
| args, ty, inst = synthesize_call(self.func.ty, args, self.node, self.ctx) | ||
| return GlobalCall(def_id=self.func.id, args=args, type_args=inst), ty | ||
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.