From 807ecbaa340054e2f47aa8b23058c51419419d27 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Mon, 22 Apr 2024 20:46:20 +0200 Subject: [PATCH] More model resource work --- wasm-component-model-resource/calculator.c | 59 ---- wasm-component-model-resource/calculator.h | 43 --- .../calculator_component_type.o | Bin 451 -> 0 bytes .../package-lock.json | 12 +- wasm-component-model-resource/package.json | 2 +- .../{calculator.rs => src/bindings.rs} | 261 ++++++++++-------- wasm-component-model-resource/src/example.ts | 189 ++++++++----- .../src/extension.ts | 32 +-- wasm-component-model-resource/src/lib.rs | 105 +++++-- wasm-component-model-resource/src/lib.rs.bak | 39 --- .../wit/calculator.wit | 4 +- .../testbed/workspace/test.txt | 1 + 12 files changed, 367 insertions(+), 380 deletions(-) delete mode 100644 wasm-component-model-resource/calculator.c delete mode 100644 wasm-component-model-resource/calculator.h delete mode 100644 wasm-component-model-resource/calculator_component_type.o rename wasm-component-model-resource/{calculator.rs => src/bindings.rs} (66%) delete mode 100644 wasm-component-model-resource/src/lib.rs.bak create mode 100644 wasm-language-server/testbed/workspace/test.txt diff --git a/wasm-component-model-resource/calculator.c b/wasm-component-model-resource/calculator.c deleted file mode 100644 index 4bcc6d1f..00000000 --- a/wasm-component-model-resource/calculator.c +++ /dev/null @@ -1,59 +0,0 @@ -// Generated by `wit-bindgen` 0.21.0. DO NOT EDIT! -#include "calculator.h" - - -__attribute__((__weak__, __export_name__("cabi_realloc"))) -void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { - (void) old_size; - if (new_size == 0) return (void*) align; - void *ret = realloc(ptr, new_size); - if (!ret) abort(); - return ret; -} - -// Helper Functions - -__attribute__((__import_module__("vscode:example/types"), __import_name__("[resource-drop]machine"))) -extern void __wasm_import_exports_vscode_example_types_machine_drop(int32_t handle); - -void exports_vscode_example_types_machine_drop_own(exports_vscode_example_types_own_machine_t handle) { - __wasm_import_exports_vscode_example_types_machine_drop(handle.__handle); -} - -__attribute__(( __import_module__("[export]vscode:example/types"), __import_name__("[resource-new]machine"))) -extern int32_t __wasm_import_exports_vscode_example_types_machine_new(int32_t); - -__attribute__((__import_module__("[export]vscode:example/types"), __import_name__("[resource-rep]machine"))) -extern int32_t __wasm_import_exports_vscode_example_types_machine_rep(int32_t); - -exports_vscode_example_types_own_machine_t exports_vscode_example_types_machine_new(exports_vscode_example_types_machine_t *rep) { - return (exports_vscode_example_types_own_machine_t) { __wasm_import_exports_vscode_example_types_machine_new((int32_t) rep) }; -} - -exports_vscode_example_types_machine_t* exports_vscode_example_types_machine_rep(exports_vscode_example_types_own_machine_t handle) { - return (exports_vscode_example_types_machine_t*) __wasm_import_exports_vscode_example_types_machine_rep(handle.__handle); -} - -__attribute__((__export_name__("vscode:example/types#[dtor]machine"))) -void __wasm_export_exports_vscode_example_types_machine_dtor(exports_vscode_example_types_machine_t* arg) { - exports_vscode_example_types_machine_destructor(arg); -} - -// Component Adapters - -__attribute__((__export_name__("vscode:example/types#[constructor]machine"))) -int32_t __wasm_export_exports_vscode_example_types_constructor_machine(int32_t arg, int32_t arg0, int32_t arg1) { - exports_vscode_example_types_own_machine_t ret = exports_vscode_example_types_constructor_machine((uint32_t) (arg), (uint32_t) (arg0), arg1); - return (ret).__handle; -} - -__attribute__((__export_name__("vscode:example/types#[method]machine.execute"))) -int32_t __wasm_export_exports_vscode_example_types_method_machine_execute(int32_t arg) { - uint32_t ret = exports_vscode_example_types_method_machine_execute(((exports_vscode_example_types_machine_t*) arg)); - return (int32_t) (ret); -} - -extern void __component_type_object_force_link_calculator(void); -void __component_type_object_force_link_calculator_public_use_in_this_compilation_unit(void) { - __component_type_object_force_link_calculator(); -} diff --git a/wasm-component-model-resource/calculator.h b/wasm-component-model-resource/calculator.h deleted file mode 100644 index d7f6e2ae..00000000 --- a/wasm-component-model-resource/calculator.h +++ /dev/null @@ -1,43 +0,0 @@ -// Generated by `wit-bindgen` 0.21.0. DO NOT EDIT! -#ifndef __BINDINGS_CALCULATOR_H -#define __BINDINGS_CALCULATOR_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -typedef uint8_t exports_vscode_example_types_operation_t; - -#define EXPORTS_VSCODE_EXAMPLE_TYPES_OPERATION_ADD 0 -#define EXPORTS_VSCODE_EXAMPLE_TYPES_OPERATION_SUB 1 -#define EXPORTS_VSCODE_EXAMPLE_TYPES_OPERATION_MUL 2 -#define EXPORTS_VSCODE_EXAMPLE_TYPES_OPERATION_DIV 3 - -typedef struct exports_vscode_example_types_own_machine_t { - int32_t __handle; -} exports_vscode_example_types_own_machine_t; - -typedef struct exports_vscode_example_types_machine_t exports_vscode_example_types_machine_t; - -typedef exports_vscode_example_types_machine_t* exports_vscode_example_types_borrow_machine_t; - -// Exported Functions from `vscode:example/types` -exports_vscode_example_types_own_machine_t exports_vscode_example_types_constructor_machine(uint32_t left, uint32_t right, exports_vscode_example_types_operation_t operation); -uint32_t exports_vscode_example_types_method_machine_execute(exports_vscode_example_types_borrow_machine_t self); - -// Helper Functions - -extern void exports_vscode_example_types_machine_drop_own(exports_vscode_example_types_own_machine_t handle); - -extern exports_vscode_example_types_own_machine_t exports_vscode_example_types_machine_new(exports_vscode_example_types_machine_t *rep); -extern exports_vscode_example_types_machine_t* exports_vscode_example_types_machine_rep(exports_vscode_example_types_own_machine_t handle); -void exports_vscode_example_types_machine_destructor(exports_vscode_example_types_machine_t *rep); - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/wasm-component-model-resource/calculator_component_type.o b/wasm-component-model-resource/calculator_component_type.o deleted file mode 100644 index f8c6dc821ff6cf99ffeff22732931cb3b52b45b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 451 zcmZ9J(MrQG7=`~o$u{R4crlbcMCaV)Kv3~5L~5J-Tcc@Gl60<*>0|g7rlJ;wT!fSF zz&R&Sgc<<=1wI3ChHxs7!3;jwQo6cvmTb&o*U(lLMz*Gi&O2*, + pub struct Engine{ + handle: _rt::Resource, } - type _MachineRep = Option; + type _EngineRep = Option; - impl Machine{ + impl Engine{ /// Creates a new resource from the specified representation. /// /// This function will create a new resource handle by moving `val` onto /// the heap and then passing that heap pointer to the component model to - /// create a handle. The owned handle is then returned as `Machine`. - pub fn new(val: T) -> Self { + /// create a handle. The owned handle is then returned as `Engine`. + pub fn new(val: T) -> Self { Self::type_guard::(); - let val: _MachineRep = Some(val); - let ptr: *mut _MachineRep = + let val: _EngineRep = Some(val); + let ptr: *mut _EngineRep = _rt::Box::into_raw(_rt::Box::new(val)); unsafe { Self::from_handle(T::_resource_new(ptr.cast())) @@ -83,20 +83,20 @@ pub mod exports { } /// Gets access to the underlying `T` which represents this resource. - pub fn get(&self) -> &T { + pub fn get(&self) -> &T { let ptr = unsafe { &*self.as_ptr::() }; ptr.as_ref().unwrap() } /// Gets mutable access to the underlying `T` which represents this /// resource. - pub fn get_mut(&mut self) -> &mut T { + pub fn get_mut(&mut self) -> &mut T { let ptr = unsafe { &mut *self.as_ptr::() }; ptr.as_mut().unwrap() } /// Consumes this resource and returns the underlying `T`. - pub fn into_inner(self) -> T { + pub fn into_inner(self) -> T { let ptr = unsafe { &mut *self.as_ptr::() }; ptr.take().unwrap() } @@ -118,7 +118,7 @@ pub mod exports { _rt::Resource::handle(&self.handle) } - // It's theoretically possible to implement the `GuestMachine` trait twice + // It's theoretically possible to implement the `GuestEngine` trait twice // so guard against using it with two different types here. #[doc(hidden)] fn type_guard() { @@ -137,25 +137,25 @@ pub mod exports { #[doc(hidden)] pub unsafe fn dtor(handle: *mut u8) { Self::type_guard::(); - let _ = _rt::Box::from_raw(handle as *mut _MachineRep); + let _ = _rt::Box::from_raw(handle as *mut _EngineRep); } - fn as_ptr(&self) -> *mut _MachineRep { - Machine::type_guard::(); + fn as_ptr(&self) -> *mut _EngineRep { + Engine::type_guard::(); T::_resource_rep(self.handle()).cast() } } - /// A borrowed version of [`Machine`] which represents a borrowed value + /// A borrowed version of [`Engine`] which represents a borrowed value /// with the lifetime `'a`. #[derive(Debug)] #[repr(transparent)] - pub struct MachineBorrow<'a> { + pub struct EngineBorrow<'a> { rep: *mut u8, - _marker: core::marker::PhantomData<&'a Machine>, + _marker: core::marker::PhantomData<&'a Engine>, } - impl<'a> MachineBorrow<'a>{ + impl<'a> EngineBorrow<'a>{ #[doc(hidden)] pub unsafe fn lift(rep: usize) -> Self { Self { @@ -165,7 +165,7 @@ pub mod exports { } /// Gets access to the underlying `T` in this resource. - pub fn get(&self) -> &T { + pub fn get(&self) -> &T { let ptr = unsafe { &mut *self.as_ptr::() }; ptr.as_ref().unwrap() } @@ -173,14 +173,14 @@ pub mod exports { // NB: mutable access is not allowed due to the component model allowing // multiple borrows of the same resource. - fn as_ptr(&self) -> *mut _MachineRep { - Machine::type_guard::(); + fn as_ptr(&self) -> *mut _EngineRep { + Engine::type_guard::(); self.rep.cast() } } - unsafe impl _rt::WasmResource for Machine{ + unsafe impl _rt::WasmResource for Engine{ #[inline] unsafe fn drop(_handle: u32) { #[cfg(not(target_arch = "wasm32"))] @@ -190,7 +190,7 @@ pub mod exports { { #[link(wasm_import_module = "[export]vscode:example/types")] extern "C" { - #[link_name = "[resource-drop]machine"] + #[link_name = "[resource-drop]engine"] fn drop(_: u32); } @@ -201,100 +201,120 @@ pub mod exports { #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_constructor_machine_cabi(arg0: i32,arg1: i32,arg2: i32,) -> i32 {#[cfg(target_arch="wasm32")] - _rt::run_ctors_once();let result0 = Machine::new(T::new(arg0 as u32, arg1 as u32, Operation::_lift(arg2 as u8))); + pub unsafe fn _export_constructor_engine_cabi() -> i32 {#[cfg(target_arch="wasm32")] + _rt::run_ctors_once();let result0 = Engine::new(T::new()); (result0).take_handle() as i32 } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_method_machine_execute_cabi(arg0: *mut u8,) -> i32 {#[cfg(target_arch="wasm32")] - _rt::run_ctors_once();let result0 = T::execute(MachineBorrow::lift(arg0 as u32 as usize).get()); - _rt::as_i32(result0) - } - pub trait Guest { - type Machine: GuestMachine; - } - pub trait GuestMachine: 'static { - - #[doc(hidden)] - unsafe fn _resource_new(val: *mut u8) -> u32 - where Self: Sized - { - #[cfg(not(target_arch = "wasm32"))] - { - let _ = val; - unreachable!(); - } - - #[cfg(target_arch = "wasm32")] - { - #[link(wasm_import_module = "[export]vscode:example/types")] - extern "C" { - #[link_name = "[resource-new]machine"] - fn new(_: *mut u8) -> u32; - } - new(val) - } - } - - #[doc(hidden)] - fn _resource_rep(handle: u32) -> *mut u8 - where Self: Sized - { - #[cfg(not(target_arch = "wasm32"))] - { - let _ = handle; - unreachable!(); - } - - #[cfg(target_arch = "wasm32")] - { - #[link(wasm_import_module = "[export]vscode:example/types")] - extern "C" { - #[link_name = "[resource-rep]machine"] - fn rep(_: u32) -> *mut u8; - } - unsafe { - rep(handle) - } - } - } - - - fn new(left: u32,right: u32,operation: Operation,) -> Self; - fn execute(&self,) -> u32; + pub unsafe fn _export_method_engine_push_operand_cabi(arg0: *mut u8,arg1: i32,) {#[cfg(target_arch="wasm32")] + _rt::run_ctors_once();T::push_operand(EngineBorrow::lift(arg0 as u32 as usize).get(), arg1 as u32); } #[doc(hidden)] - - macro_rules! __export_vscode_example_types_cabi{ - ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { - - #[export_name = "vscode:example/types#[constructor]machine"] - unsafe extern "C" fn export_constructor_machine(arg0: i32,arg1: i32,arg2: i32,) -> i32 { - $($path_to_types)*::_export_constructor_machine_cabi::<<$ty as $($path_to_types)*::Guest>::Machine>(arg0, arg1, arg2) - } - #[export_name = "vscode:example/types#[method]machine.execute"] - unsafe extern "C" fn export_method_machine_execute(arg0: *mut u8,) -> i32 { - $($path_to_types)*::_export_method_machine_execute_cabi::<<$ty as $($path_to_types)*::Guest>::Machine>(arg0) - } - - const _: () = { - #[doc(hidden)] - #[export_name = "vscode:example/types#[dtor]machine"] - #[allow(non_snake_case)] - unsafe extern "C" fn dtor(rep: *mut u8) { - $($path_to_types)*::Machine::dtor::< - <$ty as $($path_to_types)*::Guest>::Machine - >(rep) - } - }; - - };); - } - #[doc(hidden)] - pub(crate) use __export_vscode_example_types_cabi; - + #[allow(non_snake_case)] + pub unsafe fn _export_method_engine_push_operation_cabi(arg0: *mut u8,arg1: i32,) {#[cfg(target_arch="wasm32")] + _rt::run_ctors_once();T::push_operation(EngineBorrow::lift(arg0 as u32 as usize).get(), Operation::_lift(arg1 as u8)); } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_engine_execute_cabi(arg0: *mut u8,) -> i32 {#[cfg(target_arch="wasm32")] + _rt::run_ctors_once();let result0 = T::execute(EngineBorrow::lift(arg0 as u32 as usize).get()); + _rt::as_i32(result0) +} +pub trait Guest { + type Engine: GuestEngine; +} +pub trait GuestEngine: 'static { + + #[doc(hidden)] + unsafe fn _resource_new(val: *mut u8) -> u32 + where Self: Sized + { + #[cfg(not(target_arch = "wasm32"))] + { + let _ = val; + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + { + #[link(wasm_import_module = "[export]vscode:example/types")] + extern "C" { + #[link_name = "[resource-new]engine"] + fn new(_: *mut u8) -> u32; + } + new(val) + } + } + + #[doc(hidden)] + fn _resource_rep(handle: u32) -> *mut u8 + where Self: Sized + { + #[cfg(not(target_arch = "wasm32"))] + { + let _ = handle; + unreachable!(); + } + + #[cfg(target_arch = "wasm32")] + { + #[link(wasm_import_module = "[export]vscode:example/types")] + extern "C" { + #[link_name = "[resource-rep]engine"] + fn rep(_: u32) -> *mut u8; + } + unsafe { + rep(handle) + } + } + } + + + fn new() -> Self; + fn push_operand(&self,operand: u32,); + fn push_operation(&self,operation: Operation,); + fn execute(&self,) -> u32; +} +#[doc(hidden)] + +macro_rules! __export_vscode_example_types_cabi{ + ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { + + #[export_name = "vscode:example/types#[constructor]engine"] + unsafe extern "C" fn export_constructor_engine() -> i32 { + $($path_to_types)*::_export_constructor_engine_cabi::<<$ty as $($path_to_types)*::Guest>::Engine>() + } + #[export_name = "vscode:example/types#[method]engine.push-operand"] + unsafe extern "C" fn export_method_engine_push_operand(arg0: *mut u8,arg1: i32,) { + $($path_to_types)*::_export_method_engine_push_operand_cabi::<<$ty as $($path_to_types)*::Guest>::Engine>(arg0, arg1) + } + #[export_name = "vscode:example/types#[method]engine.push-operation"] + unsafe extern "C" fn export_method_engine_push_operation(arg0: *mut u8,arg1: i32,) { + $($path_to_types)*::_export_method_engine_push_operation_cabi::<<$ty as $($path_to_types)*::Guest>::Engine>(arg0, arg1) + } + #[export_name = "vscode:example/types#[method]engine.execute"] + unsafe extern "C" fn export_method_engine_execute(arg0: *mut u8,) -> i32 { + $($path_to_types)*::_export_method_engine_execute_cabi::<<$ty as $($path_to_types)*::Guest>::Engine>(arg0) + } + + const _: () = { + #[doc(hidden)] + #[export_name = "vscode:example/types#[dtor]engine"] + #[allow(non_snake_case)] + unsafe extern "C" fn dtor(rep: *mut u8) { + $($path_to_types)*::Engine::dtor::< + <$ty as $($path_to_types)*::Guest>::Engine + >(rep) + } + }; + + };); +} +#[doc(hidden)] +pub(crate) use __export_vscode_example_types_cabi; + +} } } @@ -505,15 +525,16 @@ pub(crate) use __export_calculator_impl as export; #[cfg(target_arch = "wasm32")] #[link_section = "component-type:wit-bindgen:0.24.0:calculator:encoded world"] #[doc(hidden)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 338] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd1\x01\x01A\x02\x01\ -A\x02\x01B\x09\x01m\x04\x03add\x03sub\x03mul\x03div\x04\0\x09operation\x03\0\0\x04\ -\0\x07machine\x03\x01\x01i\x02\x01@\x03\x04lefty\x05righty\x09operation\x01\0\x03\ -\x04\0\x14[constructor]machine\x01\x04\x01h\x02\x01@\x01\x04self\x05\0y\x04\0\x17\ -[method]machine.execute\x01\x06\x04\x01\x14vscode:example/types\x05\0\x04\x01\x19\ -vscode:example/calculator\x04\0\x0b\x10\x01\0\x0acalculator\x03\0\0\0G\x09produc\ -ers\x01\x0cprocessed-by\x02\x0dwit-component\x070.202.0\x10wit-bindgen-rust\x060\ -.24.0"; +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 419] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xa2\x02\x01A\x02\x01\ +A\x02\x01B\x0d\x01m\x04\x03add\x03sub\x03mul\x03div\x04\0\x09operation\x03\0\0\x04\ +\0\x06engine\x03\x01\x01i\x02\x01@\0\0\x03\x04\0\x13[constructor]engine\x01\x04\x01\ +h\x02\x01@\x02\x04self\x05\x07operandy\x01\0\x04\0\x1b[method]engine.push-operan\ +d\x01\x06\x01@\x02\x04self\x05\x09operation\x01\x01\0\x04\0\x1d[method]engine.pu\ +sh-operation\x01\x07\x01@\x01\x04self\x05\0y\x04\0\x16[method]engine.execute\x01\ +\x08\x04\x01\x14vscode:example/types\x05\0\x04\x01\x19vscode:example/calculator\x04\ +\0\x0b\x10\x01\0\x0acalculator\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0d\ +wit-component\x070.202.0\x10wit-bindgen-rust\x060.24.0"; #[inline(never)] #[doc(hidden)] diff --git a/wasm-component-model-resource/src/example.ts b/wasm-component-model-resource/src/example.ts index 194b3215..473b3050 100644 --- a/wasm-component-model-resource/src/example.ts +++ b/wasm-component-model-resource/src/example.ts @@ -14,26 +14,28 @@ export namespace example { div = 'div' } - export namespace Machine { - export interface Interface { - $handle?: $wcm.ResourceHandle; - $drop?(): void; + export namespace Engine { + export interface Interface extends $wcm.JInterface { + pushOperand(operand: u32): void; + + pushOperation(operation: Operation): void; execute(): u32; } export type Statics = { }; export type Class = Statics & { - new(left: u32, right: u32, operation: Operation): Interface; + new(): Interface; }; } - export type Machine = Machine.Interface; + export type Engine = Engine.Interface; } export type Types = { - Machine: Types.Machine.Class; + Engine: Types.Engine.Class; }; export namespace calculator { export type Imports = { + foo: () => u32; }; export type Exports = { types: example.Types; @@ -44,91 +46,140 @@ export namespace example { export namespace example { export namespace Types.$ { export const Operation = new $wcm.EnumType(['add', 'sub', 'mul', 'div']); - export const Machine = new $wcm.ResourceType('machine', 'vscode:example/types/machine'); - export const Machine_Handle = new $wcm.ResourceHandleType('machine'); - Machine.addDestructor('$drop', new $wcm.DestructorType('[resource-drop]machine', [['inst', Machine]])); - Machine.addConstructor('constructor', new $wcm.ConstructorType('[constructor]machine', [ - ['left', $wcm.u32], - ['right', $wcm.u32], + export const Engine = new $wcm.ResourceType('engine', 'vscode:example/types/engine'); + export const Engine_Handle = new $wcm.ResourceHandleType('engine'); + Engine.addDestructor('$drop', new $wcm.DestructorType('[resource-drop]engine', [['inst', Engine]])); + Engine.addConstructor('constructor', new $wcm.ConstructorType('[constructor]engine', [], new $wcm.OwnType(Engine_Handle))); + Engine.addMethod('pushOperand', new $wcm.MethodType('[method]engine.push-operand', [ + ['operand', $wcm.u32], + ], undefined)); + Engine.addMethod('pushOperation', new $wcm.MethodType('[method]engine.push-operation', [ ['operation', Operation], - ], new $wcm.OwnType(Machine_Handle))); - Machine.addMethod('execute', new $wcm.MethodType('[method]machine.execute', [], $wcm.u32)); + ], undefined)); + Engine.addMethod('execute', new $wcm.MethodType('[method]engine.execute', [], $wcm.u32)); } export namespace Types._ { export const id = 'vscode:example/types' as const; export const witName = 'types' as const; - export const types: Map = new Map([ - ['Operation', $.Operation], - ['Machine', $.Machine] - ]); - export const resources: Map = new Map([ - ['Machine', $.Machine] - ]); - export namespace Machine { + export namespace Engine { export type WasmInterface = { - '[constructor]machine': (left: i32, right: i32, operation_Operation: i32) => i32; - '[method]machine.execute': (self: i32) => i32; - '[resource-drop]machine': (self: i32) => void; + '[constructor]engine': () => i32; + '[method]engine.push-operand': (self: i32, operand: i32) => void; + '[method]engine.push-operation': (self: i32, operation_Operation: i32) => void; + '[method]engine.execute': (self: i32) => i32; }; - type ObjectModule = { - constructor(left: u32, right: u32, operation: Operation): own<$wcm.ResourceHandle>; - $drop(self: Machine): void; - execute(self: Machine): u32; + export type ObjectModule = { + constructor(): own<$wcm.ResourceHandle>; + pushOperand(self: Engine, operand: u32): void; + pushOperation(self: Engine, operation: Operation): void; + execute(self: Engine): u32; }; - class Impl extends $wcm.Resource implements example.Types.Machine.Interface { - private readonly _om: ObjectModule; - constructor(left: u32, right: u32, operation: Operation, om: ObjectModule) { - super(); - this._om = om; - this.$handle = om.constructor(left, right, operation); + export namespace imports { + export type WasmInterface = Engine.WasmInterface & { '[resource-drop]engine': (self: i32) => void }; + } + export namespace exports { + export type WasmInterface = Engine.WasmInterface & { '[dtor]engine': (self: i32) => void }; + class Impl extends $wcm.Resource implements example.Types.Engine.Interface { + private readonly _om: ObjectModule; + constructor(om: ObjectModule); + constructor(handleTag: Symbol, handle: $wcm.ResourceHandle, om: ObjectModule); + constructor(...args: any[]); + constructor(...args: any[]) { + if (args[0] === $wcm.ResourceManager.handleTag) { + super(args[1] as $wcm.ResourceHandle); + this._om = args[2] as ObjectModule; + } else { + const om = args[0] as ObjectModule; + super(om.constructor()); + this._om = om; + } + } + public pushOperand(operand: u32): void { + return this._om.pushOperand(this, operand); + } + public pushOperation(operation: Operation): void { + return this._om.pushOperation(this, operation); + } + public execute(): u32 { + return this._om.execute(this); + } } - public $drop(): void { - return this._om.$drop(this); - } - public execute(): u32 { - return this._om.execute(this); + export function Class(wasmInterface: WasmInterface, context: $wcm.WasmContext): example.Types.Engine.Class { + const resource = example.Types.$.Engine; + const om: ObjectModule = $wcm.Module.createObjectModule(resource, wasmInterface, context); + const rm: $wcm.ResourceManager = context.resources.ensure('vscode:example/types/engine'); + return class extends Impl { + constructor(); + constructor(handleTag: Symbol, handle: $wcm.ResourceHandle); + constructor(...args: any[]) { + super(...args, om); + rm.registerProxy(this); + } + }; } } - export function Class(wasmInterface: WasmInterface, context: $wcm.WasmContext): example.Types.Machine.Class { - const resource = example.Types.$.Machine; - const om: ObjectModule = $wcm.Module.createObjectModule(resource, wasmInterface, context); - return class extends Impl { - constructor(left: u32, right: u32, operation: Operation) { - super(left, right, operation, om); - } + } + export const types: Map = new Map([ + ['Operation', $.Operation], + ['Engine', $.Engine] + ]); + export const resources: Map}> = new Map}>([ + ['Engine', { resource: $.Engine, factory: Engine.exports.Class }] + ]); + export type WasmInterface = { + }; + export namespace imports { + export type WasmInterface = _.WasmInterface & Engine.imports.WasmInterface; + } + export namespace exports { + export type WasmInterface = _.WasmInterface & Engine.exports.WasmInterface; + export namespace imports { + export type WasmInterface = { + '[resource-new]engine': (rep: i32) => i32; + '[resource-rep]engine': (handle: i32) => i32; + '[resource-drop]engine': (handle: i32) => i32; }; } } - export type WasmInterface = { - } & Machine.WasmInterface; - export function createImports(service: example.Types, context: $wcm.WasmContext): WasmInterface { - return $wcm.Imports.create(undefined, resources, service, context); - } - export function filterExports(exports: object, context: $wcm.WasmContext): WasmInterface { - return $wcm.Exports.filter(exports, undefined, resources, id, undefined, context); - } - export function bindExports(wasmInterface: WasmInterface, context: $wcm.WasmContext): example.Types { - return $wcm.Exports.bind(undefined, [['Machine', $.Machine, Machine.Class]], wasmInterface, context); - } } export namespace calculator.$ { + export namespace Imports { + export const foo = new $wcm.FunctionType('foo', [], $wcm.u32); + } } export namespace calculator._ { export const id = 'vscode:example/calculator' as const; export const witName = 'calculator' as const; - export const Imports = {}; - export type Imports = {}; - export namespace Exports { + export type $Root = { + 'foo': () => i32; + }; + export type Imports = { + '[export]vscode:example/types': example.Types._.exports.imports.WasmInterface; + }; + export namespace imports { + export const functions: Map = new Map([ + ['foo', $.Imports.foo] + ]); + export function create(service: calculator.Imports, context: $wcm.WasmContext): Imports { + return $wcm.Imports.create(_, service, context); + } + export function loop(service: calculator.Imports, context: $wcm.WasmContext): calculator.Imports { + return $wcm.Imports.loop(_, service, context); + } + } + export type Exports = { + 'vscode:example/types#[constructor]engine': () => i32; + 'vscode:example/types#[method]engine.push-operand': (self: i32, operand: i32) => void; + 'vscode:example/types#[method]engine.push-operation': (self: i32, operation_Operation: i32) => void; + 'vscode:example/types#[method]engine.execute': (self: i32) => i32; + }; + export namespace exports { export const interfaces: Map = new Map([ ['Types', Types._] ]); - } - export type Exports = { - }; - export function bindExports(exports: Exports, context: $wcm.WasmContext): calculator.Exports { - const result: calculator.Exports = Object.create(null); - result.types = example.Types._.bindExports(example.Types._.filterExports(exports, context), context); - return result; + export function bind(exports: Exports, context: $wcm.WasmContext): calculator.Exports { + return $wcm.Exports.bind(_, exports, context); + } } } } diff --git a/wasm-component-model-resource/src/extension.ts b/wasm-component-model-resource/src/extension.ts index 4f20ab45..be2a697c 100644 --- a/wasm-component-model-resource/src/extension.ts +++ b/wasm-component-model-resource/src/extension.ts @@ -27,37 +27,21 @@ export async function activate(context: vscode.ExtensionContext): Promise const wasmContext: WasmContext.Default = new WasmContext.Default(); // Instantiate the module and create the necessary imports from the service implementation - const instance = await WebAssembly.instantiate(module, { - '[export]vscode:example/types' : { - '[resource-drop]machine': (...args: any[]) => { - console.log(args); - }, - '[resource-new]machine': (...args: any[]) => { - console.log(args); - return args[0]; - } - } - }); + const instance = await WebAssembly.instantiate(module, calculator._.imports.create({ foo: () => 20 }, wasmContext)); // Bind the WASM memory to the context wasmContext.initialize(new Memory.Default(instance.exports)); // Bind the JavaScript Api - const api = calculator._.bindExports(instance.exports as calculator._.Exports, wasmContext); + const api = calculator._.exports.bind(instance.exports as calculator._.Exports, wasmContext); context.subscriptions.push(vscode.commands.registerCommand('vscode-samples.wasm-component-model.run', () => { channel.show(); channel.appendLine('Running calculator example'); - const add = new api.types.Machine(1, 2, Types.Operation.add); - channel.appendLine(`Add ${add.execute()}`); - const sub = new api.types.Machine(10, 8, Types.Operation.sub); - channel.appendLine(`Sub ${sub.execute()}`); - const mul = new api.types.Machine(3, 7, Types.Operation.mul); - channel.appendLine(`Mul ${mul.execute()}`); - const div = new api.types.Machine(10, 2, Types.Operation.div); - channel.appendLine(`Div ${div.execute()}`); - // add.$drop!(); - // sub.$drop!(); - // mul.$drop!(); - // div.$drop!(); + const calculator = new api.types.Engine(); + calculator.pushOperand(10); + calculator.pushOperand(20); + calculator.pushOperation(Types.Operation.add); + const result = calculator.execute(); + channel.appendLine(`Result: ${result}`); })); } \ No newline at end of file diff --git a/wasm-component-model-resource/src/lib.rs b/wasm-component-model-resource/src/lib.rs index ba5a7e57..9715d74d 100644 --- a/wasm-component-model-resource/src/lib.rs +++ b/wasm-component-model-resource/src/lib.rs @@ -1,33 +1,102 @@ // Use a procedural macro to generate bindings for the world we specified in // `host.wit` -wit_bindgen::generate!({ - // the name of the world in the `*.wit` input file - world: "calculator", -}); +// wit_bindgen::generate!({ +// // the name of the world in the `*.wit` input file +// world: "calculator", +// }); -use exports::vscode::example::types::Guest; +mod bindings; -use crate::exports::vscode::example::types::{ GuestEngine, Operation }; +use std::cell::RefCell; +use crate::bindings::exports::vscode::example::types::{ Guest, GuestEngine, Operation }; + + +enum StackElement { + Operand(u32), + Operation(Operation), +} + +struct Stack { + values: Vec +} + +impl Stack { + fn new() -> Self { + Stack { + values: Vec::new() + } + } + + fn push_operand(&mut self, operand: u32) { + self.values.push(StackElement::Operand(operand)); + } + + fn push_operation(&mut self, operation: Operation) { + self.values.push(StackElement::Operation(operation)); + } + + fn execute(&mut self) -> u32 { + let mut result = 0; + let mut left = 0; + let mut right = 0; + let mut operation: &Operation = &Operation::Add; + self.values.reverse(); + let iter = self.values.iter(); + for element in iter { + match element { + StackElement::Operand(operand) => { + if left == 0 { + left = *operand; + } else { + right = *operand; + } + }, + StackElement::Operation(op) => { + match operation { + Operation::Add => { + result = left + right; + }, + Operation::Sub => { + result = left - right; + }, + Operation::Mul => { + result = left * right; + }, + Operation::Div => { + result = left / right; + }, + } + operation = op; + } + } + } + self.values.clear(); + return result; + } +} struct CalcEngine { - left: u32, - right: u32, - operation: Operation, + stack: RefCell, } impl GuestEngine for CalcEngine { - fn new(left: u32, right: u32, operation: Operation) -> Self { - Self { left, right, operation } + fn new() -> Self { + CalcEngine { + stack: RefCell::new(Stack::new()) + } + } + + fn push_operand(&self, operand: u32) { + self.stack.borrow_mut().push_operand(operand); + } + + fn push_operation(&self,operation:Operation,) { + self.stack.borrow_mut().push_operation(operation); } fn execute(&self) -> u32 { - match self.operation { - Operation::Add => self.left + self.right, - Operation::Sub => self.left - self.right, - Operation::Mul => self.left * self.right, - Operation::Div => self.left / self.right, - } + return self.stack.borrow_mut().execute(); } } @@ -36,4 +105,4 @@ impl Guest for Implementation { type Engine = CalcEngine; } -export!(Implementation); \ No newline at end of file +bindings::export!(Implementation with_types_in bindings); \ No newline at end of file diff --git a/wasm-component-model-resource/src/lib.rs.bak b/wasm-component-model-resource/src/lib.rs.bak deleted file mode 100644 index 6dcc2854..00000000 --- a/wasm-component-model-resource/src/lib.rs.bak +++ /dev/null @@ -1,39 +0,0 @@ -// Use a procedural macro to generate bindings for the world we specified in -// `host.wit` -wit_bindgen::generate!({ - // the name of the world in the `*.wit` input file - world: "calculator", -}); - -use exports::vscode::example::types::Guest; - -use crate::exports::vscode::example::types::{ GuestMachine, Operation }; - -struct CalcMachine { - left: u32, - right: u32, - operation: Operation, -} - -impl GuestMachine for CalcMachine { - - fn new(left: u32, right: u32, operation: Operation) -> Self { - Self { left, right, operation } - } - - fn execute(&self) -> u32 { - match self.operation { - Operation::Add => self.left + self.right, - Operation::Sub => self.left - self.right, - Operation::Mul => self.left * self.right, - Operation::Div => self.left / self.right, - } - } -} - -struct Implementation; -impl Guest for Implementation { - type Machine = CalcMachine; -} - -export!(Implementation); \ No newline at end of file diff --git a/wasm-component-model-resource/wit/calculator.wit b/wasm-component-model-resource/wit/calculator.wit index 2a0a6728..90923854 100644 --- a/wasm-component-model-resource/wit/calculator.wit +++ b/wasm-component-model-resource/wit/calculator.wit @@ -11,7 +11,9 @@ interface types { } resource engine { - constructor(left: u32, right: u32, operation: operation); + constructor(); + push-operand: func(operand: u32); + push-operation: func(operation: operation); execute: func() -> u32; } } diff --git a/wasm-language-server/testbed/workspace/test.txt b/wasm-language-server/testbed/workspace/test.txt new file mode 100644 index 00000000..a9ed77c8 --- /dev/null +++ b/wasm-language-server/testbed/workspace/test.txt @@ -0,0 +1 @@ +Some text. \ No newline at end of file