@ -1,6 +1,7 @@
const std = @import ( " std " ) ;
const assert = std . debug . assert ;
const panic = std . debug . panic ;
const c_alloc = std . heap . c_allocator ;
const Store = @import ( " ./store.zig " ) . Store ;
const Extern = @import ( " ./extern.zig " ) . Extern ;
@ -98,7 +99,7 @@ pub const Func = extern struct {
. callback = & ( struct {
const meta = @typeInfo ( @TypeOf ( func ) ) . Fn ;
const ArgsType = std . meta . ArgsTuple ( @TypeOf ( func ) ) ;
const Resul tType = meta . return_type orelse void ;
const Return Type = meta . return_type orelse void ;
fn callback (
env : ? * anyopaque ,
@ -118,7 +119,7 @@ pub const Func = extern struct {
}
assert ( num_args = = meta . params . len - offset ) ;
assert ( num_results = = getNumResultsFromResul tType ( Resul tType ) ) ;
assert ( num_results = = getNumResultsFromReturn Type ( Return Type ) ) ;
/ / Turn the " env " parameter back into a function pointer .
const func_ptr : * const @TypeOf ( func ) = @ptrCast ( env ) ;
@ -129,13 +130,24 @@ pub const Func = extern struct {
panic ( " Cannot convert {} to {s} " , . { arg , @typeName ( p . type . ? ) } ) ;
/ / Call the function with the arguments , get the results .
const func_results = @call ( . auto , func_ptr , func_args ) ;
const func_results_maybe_error = @call ( . auto , func_ptr , func_args ) ;
/ / If function returns an ErrorUnion , convert it to
/ / its payload , or return a trap if an error occurred .
const func_results = if ( @typeInfo ( @TypeOf ( func_results_maybe_error ) ) = = . ErrorUnion )
func_results_maybe_error catch | err | {
const fmt = " Error '{s}' occurred in host code " ;
const msg = std . fmt . allocPrintZ ( c_alloc , fmt , . { @errorName ( err ) } ) ;
return Trap . init ( msg catch " Error occurred in host code " ) ;
}
else
func_results_maybe_error ;
/ / Pass the result ( s ) back to WASM .
if ( comptime std . meta . trait . isTuple ( ResultType ) ) {
if ( comptime std . meta . trait . isTuple ( @TypeOf ( func_results ) ) ) {
inline for ( func_results , 0 . . ) | res , i |
results [ i ] = Val . fromValue ( @TypeOf ( res ) , res ) ;
} else if ( ResultType ! = void )
} else if ( @TypeOf ( func_results ) ! = void )
results [ 0 ] = Val . fromValue ( @TypeOf ( func_results ) , func_results ) ;
return null ;
@ -165,7 +177,7 @@ pub const Func = extern struct {
val . * = Val . fromValue ( @TypeOf ( arg ) , arg ) ;
/ / Set up function results .
const num_results = comptime getNumResultsFromResul tType ( TResult ) ;
const num_results = comptime getNumResultsFromReturn Type ( TResult ) ;
var results_array : [ num_results ] Val = undefined ;
var trap : ? * Trap = null ;
@ -198,10 +210,16 @@ pub const Func = extern struct {
} ;
}
fn getNumResultsFromResultType ( comptime T : type ) usize {
return comptime if ( std . meta . trait . isTuple ( T ) )
@typeInfo ( T ) . Struct . fields . len
else if ( T ! = void ) 1 else 0 ;
fn getNumResultsFromReturnType ( comptime T : type ) usize {
const meta = @typeInfo ( T ) ;
return comptime if ( meta = = . ErrorUnion )
getNumResultsFromReturnType ( meta . ErrorUnion . payload )
else if ( std . meta . trait . isTuple ( T ) )
meta . Struct . fields . len
else if ( T ! = void )
1
else
0 ;
}
pub const Callback = fn (
@ -257,7 +275,11 @@ pub const FuncType = opaque {
inline for ( meta . params [ offset . . ] , 0 . . ) | p , i |
params . data [ i ] = ValType . fromType ( p . type . ? ) ;
const ResultType = meta . return_type orelse void ;
const ResultType = switch ( @typeInfo ( meta . return_type orelse void ) ) {
. ErrorUnion = > | u | u . payload ,
else = > | t | t ,
} ;
var results = if ( comptime std . meta . trait . isTuple ( ResultType ) ) blk : {
var res = ValTypeVec . initUninitialized ( ResultType . len ) ;
inline for ( ResultType , res . toSlice ( ) ) | T , * r |