///|
fn source_integer_reference(
ctx : Lowering,
name : @ir.FQName,
expected : Lowered,
context : String,
) -> String raise {
let module_name = name.module_name.to_canonical()
if !ctx.source_extensions.contains(module_name) {
raise Invalid(
"moonbit.missing_source_extension",
context,
name.to_canonical(),
)
}
if module_name == "integer" {
let operation = name.local_name.to_canonical()
let boolean = [
"equal", "not-equal", "less-than", "less-than-or-equal", "greater-than", "greater-than-or-equal",
].contains(operation)
let arithmetic = ["add", "subtract", "multiply", "negate", "require-budget"].contains(
operation,
)
if !boolean && !arithmetic {
raise Invalid(
"moonbit.unsupported_source_extension",
context,
name.to_canonical(),
)
}
let integer = Atom(Scalar::Integer)
let output = if boolean { Atom(Scalar::Boolean) } else { integer }
let unary = operation == "negate" || operation == "require-budget"
let signature = if unary {
Arrow(integer, output)
} else {
Arrow(integer, Arrow(integer, output))
}
if expected != signature {
raise Invalid(
"moonbit.source_extension_signature",
context,
name.to_canonical(),
)
}
ctx.imports["source_integer"] = true
ctx.imports["integer"] = true
return curry_source(
ctx,
if unary {
[("a0", integer)]
} else {
[("a0", integer), ("a1", integer)]
},
output,
"@source_integer." +
operation.replace(old="-", new="_") +
(if unary { "(a0)" } else { "(a0, a1)" }),
)
}
let width = match module_name {
"int16" => "int-16"
"int64" => "int-64"
"byte" => "byte"
"uint16" => "uint-16"
"uint32" => "uint-32"
"uint64" => "uint-64"
_ =>
raise Invalid(
"moonbit.unsupported_source_extension",
context,
name.to_canonical(),
)
}
if name.local_name.to_canonical() != "normalize" ||
expected != Arrow(Atom(Integer), Atom(BoundedInteger(width))) {
raise Invalid(
"moonbit.source_extension_signature",
context,
name.to_canonical(),
)
}
ctx.imports["source_integer"] = true
ctx.imports["integer"] = true
ctx.imports["int"] = true
curry_source(
ctx,
[("a0", Atom(Integer))],
Atom(BoundedInteger(width)),
"@source_integer.normalize_" + module_name + "(a0)",
)
}