///|
priv struct OperatorCommandSpec {
name : String
canonical_name : String
}
///|
let big_operator_commands : Array[OperatorCommandSpec] = [
{ name: "\\coprod", canonical_name: "\\coprod" },
{ name: "\\bigvee", canonical_name: "\\bigvee" },
{ name: "\\bigwedge", canonical_name: "\\bigwedge" },
{ name: "\\biguplus", canonical_name: "\\biguplus" },
{ name: "\\bigcap", canonical_name: "\\bigcap" },
{ name: "\\bigcup", canonical_name: "\\bigcup" },
{ name: "\\intop", canonical_name: "\\intop" },
{ name: "\\prod", canonical_name: "\\prod" },
{ name: "\\sum", canonical_name: "\\sum" },
{ name: "\\bigotimes", canonical_name: "\\bigotimes" },
{ name: "\\bigoplus", canonical_name: "\\bigoplus" },
{ name: "\\bigodot", canonical_name: "\\bigodot" },
{ name: "\\bigsqcup", canonical_name: "\\bigsqcup" },
{ name: "\\smallint", canonical_name: "\\smallint" },
{ name: "∏", canonical_name: "\\prod" },
{ name: "∐", canonical_name: "\\coprod" },
{ name: "∑", canonical_name: "\\sum" },
{ name: "⋀", canonical_name: "\\bigwedge" },
{ name: "⋁", canonical_name: "\\bigvee" },
{ name: "⋂", canonical_name: "\\bigcap" },
{ name: "⋃", canonical_name: "\\bigcup" },
{ name: "⨀", canonical_name: "\\bigodot" },
{ name: "⨁", canonical_name: "\\bigoplus" },
{ name: "⨂", canonical_name: "\\bigotimes" },
{ name: "⨄", canonical_name: "\\biguplus" },
{ name: "⨆", canonical_name: "\\bigsqcup" },
]
///|
let integral_operator_commands : Array[OperatorCommandSpec] = [
{ name: "\\int", canonical_name: "\\int" },
{ name: "\\iint", canonical_name: "\\iint" },
{ name: "\\iiint", canonical_name: "\\iiint" },
{ name: "\\oint", canonical_name: "\\oint" },
{ name: "\\oiint", canonical_name: "\\oiint" },
{ name: "\\oiiint", canonical_name: "\\oiiint" },
{ name: "∫", canonical_name: "\\int" },
{ name: "∬", canonical_name: "\\iint" },
{ name: "∭", canonical_name: "\\iiint" },
{ name: "∮", canonical_name: "\\oint" },
{ name: "∯", canonical_name: "\\oiint" },
{ name: "∰", canonical_name: "\\oiiint" },
]
///|
let named_operator_commands : Array[String] = [
"\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos",
"\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg",
"\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin",
"\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th",
]
///|
let limited_named_operator_commands : Array[String] = [
"\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup",
]
///|
fn operator_names(commands : Array[OperatorCommandSpec]) -> Array[String] {
commands.map(command => command.name)
}
///|
fn canonical_operator_name(
commands : Array[OperatorCommandSpec],
func_name : String,
) -> String raise ParseFailure {
for command in commands {
guard command.name == func_name else { continue }
return command.canonical_name
}
raise InternalInvariant(message="Unknown operator command: " + func_name)
}
///|
fn symbol_operator(mode : Mode, limits : Bool, name : String) -> ParseNode {
Op(
mode~,
limits~,
always_handle_sup_sub=false,
parent_is_sup_sub=false,
suppress_base_shift=false,
content=SymbolOperator(name),
)
}
///|
fn named_operator(mode : Mode, limits : Bool, name : String) -> ParseNode {
Op(
mode~,
limits~,
always_handle_sup_sub=false,
parent_is_sup_sub=false,
suppress_base_shift=false,
content=NamedOperator(name),
)
}
///|
fn big_operator_spec() -> FunctionSpec {
FunctionSpec::make(
operator_names(big_operator_commands),
0,
handler=big_operator_handler,
)
}
///|
fn big_operator_handler(
context : FunctionContext,
_args : Array[ParseNode],
_opt_args : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
symbol_operator(
context.mode,
true,
canonical_operator_name(big_operator_commands, context.func_name),
)
}
///|
fn mathop_spec() -> FunctionSpec {
FunctionSpec::make(["\\mathop"], 1, primitive=true, handler=mathop_handler)
}
///|
fn mathop_handler(
context : FunctionContext,
args : Array[ParseNode],
_opt_args : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
Op(
mode=context.mode,
limits=false,
always_handle_sup_sub=false,
parent_is_sup_sub=false,
suppress_base_shift=false,
content=BodyOperator(
ord_argument(require_function_arg(args, 0, context.func_name)),
),
)
}
///|
fn named_operator_spec() -> FunctionSpec {
FunctionSpec::make(named_operator_commands, 0, handler=named_operator_handler)
}
///|
#warnings("-unused_error_type")
fn named_operator_handler(
context : FunctionContext,
_args : Array[ParseNode],
_opt_args : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
named_operator(context.mode, false, context.func_name)
}
///|
fn limited_named_operator_spec() -> FunctionSpec {
FunctionSpec::make(
limited_named_operator_commands,
0,
handler=limited_named_operator_handler,
)
}
///|
#warnings("-unused_error_type")
fn limited_named_operator_handler(
context : FunctionContext,
_args : Array[ParseNode],
_opt_args : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
named_operator(context.mode, true, context.func_name)
}
///|
fn integral_operator_spec() -> FunctionSpec {
FunctionSpec::make(
operator_names(integral_operator_commands),
0,
allowed_in_argument=true,
handler=integral_operator_handler,
)
}
///|
fn integral_operator_handler(
context : FunctionContext,
_args : Array[ParseNode],
_opt_args : Array[ParseNode?],
) -> ParseNode raise ParseFailure {
symbol_operator(
context.mode,
false,
canonical_operator_name(integral_operator_commands, context.func_name),
)
}