///|
fn source_float_reference(
ctx : Lowering,
name : @ir.FQName,
expected : Lowered,
context : String,
) -> String raise {
if !ctx.source_extensions.contains("float32") {
raise Invalid(
"moonbit.missing_source_extension",
context,
name.to_canonical(),
)
}
let operation = name.local_name.to_canonical()
let float = Atom(Scalar::Float32)
let float64 = Atom(Scalar::Float)
let boolean = [
"equal", "not-equal", "less-than", "less-than-or-equal", "greater-than", "greater-than-or-equal",
].contains(operation)
let unary = operation == "from-float64" ||
operation == "negate" ||
operation == "round-boundary"
if !unary &&
!boolean &&
!["add", "subtract", "multiply", "divide"].contains(operation) {
raise Invalid(
"moonbit.unsupported_source_extension",
context,
name.to_canonical(),
)
}
let result = if boolean { Atom(Scalar::Boolean) } else { float }
let signature = if unary {
Arrow(if operation == "from-float64" { float64 } else { float }, result)
} else {
Arrow(float, Arrow(float, result))
}
if expected != signature {
raise Invalid(
"moonbit.source_extension_signature",
context,
name.to_canonical(),
)
}
ctx.imports["source_float"] = true
let arguments = if unary {
[("a0", if operation == "from-float64" { float64 } else { float })]
} else {
[("a0", float), ("a1", float)]
}
let body = match operation {
"from-float64" => "@source_float.round32(a0)"
"round-boundary" => "@source_float.round32(a0)"
"negate" => "@source_float.negate32(a0)"
"add" | "subtract" | "multiply" | "divide" =>
"@source_float." + operation + "32(a0, a1)"
_ => {
let lhs = "@source_float.round32(a0)"
let rhs = "@source_float.round32(a1)"
let comparator = match operation {
"equal" => "=="
"not-equal" => "!="
"less-than" => "<"
"less-than-or-equal" => "<="
"greater-than" => ">"
_ => ">="
}
"(" + lhs + " " + comparator + " " + rhs + ")"
}
}
curry_source(ctx, arguments, result, body)
}