@@ -13,7 +13,7 @@ use crate::{
13
13
EelFunctionType ,
14
14
} ;
15
15
use parity_wasm:: elements:: {
16
- CodeSection , ExportEntry , ExportSection , External , Func , FuncBody , FunctionSection ,
16
+ BlockType , CodeSection , ExportEntry , ExportSection , External , Func , FuncBody , FunctionSection ,
17
17
FunctionType , GlobalEntry , GlobalSection , GlobalType , ImportEntry , ImportSection , InitExpr ,
18
18
Instruction , Instructions , Internal , Module , Section , Serialize , Type , TypeSection , ValueType ,
19
19
} ;
@@ -308,31 +308,38 @@ impl Emitter {
308
308
309
309
fn emit_function_call (
310
310
& mut self ,
311
- function_call : FunctionCall ,
311
+ mut function_call : FunctionCall ,
312
312
instructions : & mut Vec < Instruction > ,
313
313
) -> EmitterResult < ( ) > {
314
- let arity = function_call. arguments . len ( ) ;
315
- for arg in function_call. arguments {
316
- & self . emit_expression ( arg, instructions) ?;
317
- }
318
- // TODO: Assert arrity
319
314
match & function_call. name . name [ ..] {
320
315
"int" => {
316
+ assert_arity ( & function_call, 1 ) ?;
317
+ for arg in function_call. arguments {
318
+ self . emit_expression ( arg, instructions) ?;
319
+ }
321
320
instructions. push ( Instruction :: F64Floor ) ;
322
321
}
322
+ "if" => {
323
+ assert_arity ( & function_call, 3 ) ?;
324
+
325
+ let alternate = function_call. arguments . pop ( ) . unwrap ( ) ;
326
+ let consiquent = function_call. arguments . pop ( ) . unwrap ( ) ;
327
+ let test = function_call. arguments . pop ( ) . unwrap ( ) ;
328
+
329
+ self . emit_expression ( test, instructions) ?;
330
+ emit_is_not_zeroish ( instructions) ;
331
+ instructions. push ( Instruction :: If ( BlockType :: Value ( ValueType :: F64 ) ) ) ;
332
+ self . emit_expression ( consiquent, instructions) ?;
333
+ instructions. push ( Instruction :: Else ) ;
334
+ self . emit_expression ( alternate, instructions) ?;
335
+ instructions. push ( Instruction :: End ) ;
336
+ }
323
337
shim_name if Shim :: from_str ( shim_name) . is_some ( ) => {
324
338
let shim = Shim :: from_str ( shim_name) . unwrap ( ) ;
325
- if arity != shim. arity ( ) {
326
- return Err ( CompilerError :: new (
327
- format ! (
328
- "Incorrect argument count for function `{}`. Expected {} but got {}." ,
329
- shim_name,
330
- shim. arity( ) ,
331
- arity
332
- ) ,
333
- // TODO: Better to underline the argument list
334
- function_call. name . span ,
335
- ) ) ;
339
+ assert_arity ( & function_call, shim. arity ( ) ) ?;
340
+
341
+ for arg in function_call. arguments {
342
+ self . emit_expression ( arg, instructions) ?;
336
343
}
337
344
instructions. push ( Instruction :: Call ( self . shims . get ( shim) ) ) ;
338
345
}
@@ -365,6 +372,12 @@ impl Emitter {
365
372
}
366
373
}
367
374
375
+ fn emit_is_not_zeroish ( instructions : & mut Vec < Instruction > ) {
376
+ instructions. push ( Instruction :: F64Abs ) ;
377
+ instructions. push ( Instruction :: F64Const ( f64_const ( EPSILON ) ) ) ;
378
+ instructions. push ( Instruction :: F64Gt ) ;
379
+ }
380
+
368
381
// TODO: There's got to be a better way.
369
382
fn f64_const ( value : f64 ) -> u64 {
370
383
u64:: from_le_bytes ( value. to_le_bytes ( ) )
@@ -393,3 +406,20 @@ fn make_import_entry(module_str: String, field_str: String) -> ImportEntry {
393
406
External :: Global ( GlobalType :: new ( ValueType :: F64 , true ) ) ,
394
407
)
395
408
}
409
+
410
+ fn assert_arity ( function_call : & FunctionCall , arity : usize ) -> EmitterResult < ( ) > {
411
+ if function_call. arguments . len ( ) != arity {
412
+ Err ( CompilerError :: new (
413
+ format ! (
414
+ "Incorrect argument count for function `{}`. Expected {} but got {}." ,
415
+ function_call. name. name,
416
+ arity,
417
+ function_call. arguments. len( )
418
+ ) ,
419
+ // TODO: Better to underline the argument list
420
+ function_call. name . span ,
421
+ ) )
422
+ } else {
423
+ Ok ( ( ) )
424
+ }
425
+ }
0 commit comments