///|
/// Additive MoonBit numeric SDK inventory. The pinned classic specification is
/// copied before extension so its oracle count and declarations remain stable.
pub fn numeric_sdk_specification() -> @ir.PackageSpecification raise {
let classic = sdk_specification()
let modules = Map::from_array(classic.modules.iter().collect())
let int_path = @ir.Path::parse("int")
let classic_int = modules[int_path]
let types = Map::from_array(classic_int.types.iter().collect())
let values = Map::from_array(classic_int.values.iter().collect())
let attrs = @ir.TypeAttributes::default()
let exact = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#int"),
[],
)
let provenance = @ir.Annotation::Compact(
@ir.FQName::parse("morphir/moonbit-source:numeric#sdk-extension"),
Some("morphir-sdk-moonbit-numeric-v1"),
)
for
(name, source_name) in [
("byte", "Byte"),
("uint-16", "UInt16"),
("uint-32", "UInt32"),
("uint-64", "UInt64"),
] {
let bounded = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:int#" + name),
[],
)
types[@ir.Name::parse(name)] = @ir.Documented::{
doc: Some(source_name + " unsigned boundary type"),
value: @ir.TypeSpecification::{
annotations: [provenance],
body: @ir.TypeSpecificationBody::OpaqueTypeSpecification([]),
},
}
values[@ir.Name::parse("from-" + name)] = @ir.Documented::{
doc: Some("Exact nonnegative widening from " + source_name),
value: @ir.ValueSpecification::{
inputs: [(@ir.Name::parse("value"), bounded)],
output: exact,
annotations: [provenance],
},
}
values[@ir.Name::parse("to-" + name)] = @ir.Documented::{
doc: Some("Checked narrowing to " + source_name),
value: @ir.ValueSpecification::{
inputs: [(@ir.Name::parse("value"), exact)],
output: @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:maybe#maybe"),
[bounded],
),
annotations: [provenance],
},
}
}
let float64 = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#float"),
[],
)
let float32 = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/moonbit-source:float32#float32"),
[],
)
for
(name, input, output, policy) in [
("from-float64-exact", float64, exact, "checked-exact"),
("from-float64-truncated", float64, exact, "truncated"),
("from-float64-floor", float64, exact, "floor"),
("from-float64-ceiling", float64, exact, "ceiling"),
("from-float64-rounded", float64, exact, "rounded"),
("from-float32-exact", float32, exact, "checked-exact"),
("from-float32-truncated", float32, exact, "truncated"),
("from-float32-floor", float32, exact, "floor"),
("from-float32-ceiling", float32, exact, "ceiling"),
("from-float32-rounded", float32, exact, "rounded"),
("to-float64-exact", exact, float64, "checked-exact"),
("to-float64-rounded", exact, float64, "rounded"),
("to-float32-exact", exact, float32, "checked-exact"),
("to-float32-rounded", exact, float32, "rounded"),
] {
values[@ir.Name::parse(name)] = @ir.Documented::{
doc: Some("MoonBit numeric conversion policy: " + policy),
value: @ir.ValueSpecification::{
inputs: [(@ir.Name::parse("value"), input)],
output: if name.has_suffix("exact") || name.has_prefix("from-float") {
@ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:maybe#maybe"),
[output],
)
} else {
output
},
annotations: [provenance],
},
}
}
modules[int_path] = @ir.ModuleSpecification::{
types,
values,
doc: classic_int.doc,
annotations: classic_int.annotations,
}
let decimal = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:decimal#decimal"),
[],
)
let text = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:string#string"),
[],
)
let checked_values = Map([])
let checked_provenance = @ir.Annotation::Compact(
@ir.FQName::parse("morphir/moonbit-source:numeric#sdk-extension"),
Some("morphir-sdk-decimal-checked-v1"),
)
for
(name, inputs) in [
("from-string-exact", [text]),
("divide", [decimal, decimal]),
("divide-with-default", [decimal, decimal, decimal]),
] {
checked_values[@ir.Name::parse(name)] = @ir.Documented::{
doc: Some(
"Checked Decimal v1: exact construction; division truncates at -32 with distinct zero-divisor and underflow errors; fallback is opt-in",
),
value: @ir.ValueSpecification::{
inputs: inputs.mapi((i, ty) => {
(@ir.Name::parse("arg-" + i.to_string()), ty)
}),
output: decimal,
annotations: [checked_provenance],
},
}
}
modules[@ir.Path::parse("decimal-checked-v1")] = @ir.ModuleSpecification::{
types: Map([]),
values: checked_values,
doc: None,
annotations: [checked_provenance],
}
{ modules, }
}
///|
pub fn source_integer_specification() -> @ir.PackageSpecification raise {
let attrs = @ir.TypeAttributes::default()
let exact = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#int"),
[],
)
let modules = Map([])
modules[@ir.Path::parse("numeric")] = @ir.ModuleSpecification::{
types: Map::from_array([
(
@ir.Name::parse("sdk-extension"),
@ir.Documented::{
doc: Some("Versioned MoonBit numeric SDK provenance marker"),
value: @ir.TypeSpecification::{
annotations: [],
body: @ir.TypeSpecificationBody::OpaqueTypeSpecification([]),
},
},
),
]),
values: Map([]),
doc: None,
annotations: [],
}
let boolean = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#bool"),
[],
)
let integer_values = Map([])
for
(name, arity, boolean_result) in [
("add", 2, false),
("subtract", 2, false),
("multiply", 2, false),
("negate", 1, false),
("require-budget", 1, false),
("equal", 2, true),
("not-equal", 2, true),
("less-than", 2, true),
("less-than-or-equal", 2, true),
("greater-than", 2, true),
("greater-than-or-equal", 2, true),
] {
integer_values[@ir.Name::parse(name)] = @ir.Documented::{
doc: Some("Bounded exact MoonBit source integer operation"),
value: @ir.ValueSpecification::{
inputs: if arity == 1 {
[(@ir.Name::parse("value"), exact)]
} else {
[(@ir.Name::parse("left"), exact), (@ir.Name::parse("right"), exact)]
},
output: if boolean_result {
boolean
} else {
exact
},
annotations: [
@ir.Annotation::Compact(
@ir.FQName::parse("morphir/moonbit-source:numeric#sdk-extension"),
Some("morphir-moonbit-source-integer-v1"),
),
],
},
}
}
modules[@ir.Path::parse("integer")] = @ir.ModuleSpecification::{
types: Map([]),
values: integer_values,
doc: None,
annotations: [],
}
for
(module_name, type_name) in [
("int16", "int-16"),
("int64", "int-64"),
("byte", "byte"),
("uint16", "uint-16"),
("uint32", "uint-32"),
("uint64", "uint-64"),
] {
modules[@ir.Path::parse(module_name)] = @ir.ModuleSpecification::{
types: Map([]),
values: Map::from_array([
(
@ir.Name::parse("normalize"),
@ir.Documented::{
doc: Some("MoonBit source-width normalization"),
value: @ir.ValueSpecification::{
inputs: [(@ir.Name::parse("value"), exact)],
output: @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:int#" + type_name),
[],
),
annotations: [
@ir.Annotation::Compact(
@ir.FQName::parse(
"morphir/moonbit-source:numeric#sdk-extension",
),
Some("morphir-moonbit-source-integer-v1"),
),
],
},
},
),
]),
doc: None,
annotations: [],
}
}
{ modules, }
}
///|
/// Binary32 source operations are separate from the classic Float64 SDK oracle.
pub fn source_float_specification() -> @ir.PackageSpecification raise {
let attrs = @ir.TypeAttributes::default()
let float32 = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/moonbit-source:float32#float32"),
[],
)
let float64 = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#float"),
[],
)
let boolean = @ir.Type::Reference(
attrs,
@ir.FQName::parse("morphir/SDK:basics#bool"),
[],
)
let provenance = @ir.Annotation::Compact(
@ir.FQName::parse("morphir/moonbit-source:numeric#sdk-extension"),
Some("morphir-moonbit-source-float-v1"),
)
let values = Map([])
values[@ir.Name::parse("from-float64")] = @ir.Documented::{
doc: Some("Round Float64 to source binary32"),
value: @ir.ValueSpecification::{
inputs: [(@ir.Name::parse("value"), float64)],
output: float32,
annotations: [provenance],
},
}
for
(name, arity, is_boolean) in [
("add", 2, false),
("subtract", 2, false),
("multiply", 2, false),
("divide", 2, false),
("negate", 1, false),
("round-boundary", 1, false),
("equal", 2, true),
("not-equal", 2, true),
("less-than", 2, true),
("less-than-or-equal", 2, true),
("greater-than", 2, true),
("greater-than-or-equal", 2, true),
] {
values[@ir.Name::parse(name)] = @ir.Documented::{
doc: Some("MoonBit source binary32 operation"),
value: @ir.ValueSpecification::{
inputs: if arity == 1 {
[(@ir.Name::parse("value"), float32)]
} else {
[
(@ir.Name::parse("left"), float32),
(@ir.Name::parse("right"), float32),
]
},
output: if is_boolean {
boolean
} else {
float32
},
annotations: [provenance],
},
}
}
{
modules: Map::from_array([
(
@ir.Path::parse("float32"),
@ir.ModuleSpecification::{
types: Map::from_array([
(
@ir.Name::parse("float32"),
@ir.Documented::{
doc: Some("MoonBit source IEEE binary32"),
value: @ir.TypeSpecification::{
annotations: [provenance],
body: @ir.TypeSpecificationBody::OpaqueTypeSpecification([]),
},
},
),
]),
values,
doc: None,
annotations: [provenance],
},
),
]),
}
}