Skip to content

Commit 29badc2

Browse files
committed
If function
1 parent d27c45a commit 29badc2

File tree

4 files changed

+52
-22
lines changed

4 files changed

+52
-22
lines changed

compiler-rs/src/emitter.rs

+48-18
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
EelFunctionType,
1414
};
1515
use parity_wasm::elements::{
16-
CodeSection, ExportEntry, ExportSection, External, Func, FuncBody, FunctionSection,
16+
BlockType, CodeSection, ExportEntry, ExportSection, External, Func, FuncBody, FunctionSection,
1717
FunctionType, GlobalEntry, GlobalSection, GlobalType, ImportEntry, ImportSection, InitExpr,
1818
Instruction, Instructions, Internal, Module, Section, Serialize, Type, TypeSection, ValueType,
1919
};
@@ -308,31 +308,38 @@ impl Emitter {
308308

309309
fn emit_function_call(
310310
&mut self,
311-
function_call: FunctionCall,
311+
mut function_call: FunctionCall,
312312
instructions: &mut Vec<Instruction>,
313313
) -> 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
319314
match &function_call.name.name[..] {
320315
"int" => {
316+
assert_arity(&function_call, 1)?;
317+
for arg in function_call.arguments {
318+
self.emit_expression(arg, instructions)?;
319+
}
321320
instructions.push(Instruction::F64Floor);
322321
}
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+
}
323337
shim_name if Shim::from_str(shim_name).is_some() => {
324338
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)?;
336343
}
337344
instructions.push(Instruction::Call(self.shims.get(shim)));
338345
}
@@ -365,6 +372,12 @@ impl Emitter {
365372
}
366373
}
367374

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+
368381
// TODO: There's got to be a better way.
369382
fn f64_const(value: f64) -> u64 {
370383
u64::from_le_bytes(value.to_le_bytes())
@@ -393,3 +406,20 @@ fn make_import_entry(module_str: String, field_str: String) -> ImportEntry {
393406
External::Global(GlobalType::new(ValueType::F64, true)),
394407
)
395408
}
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+
}

compiler-rs/tests/compatibility_test.rs

-4
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,6 @@ fn compatibility_tests() {
354354
"Acos",
355355
"Atan",
356356
"Atan2",
357-
"if",
358-
"if",
359-
"if does short-circit (consiquent)",
360-
"if does short-circit (alternate)",
361357
"above (true)",
362358
"above (false)",
363359
"below (true)",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
if(1,2)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if(1,2)
2+
========================================================================
3+
Incorrect argument count for function `if`. Expected 3 but got 2.

0 commit comments

Comments
 (0)