类型后端

计算器引擎的数值实现由 5 个 SimpleCalculatorFactory 子类提供,全部位于 openmods.calc.types。它们共享同一套构建契约(src/main/java/openmods/calc/SimpleCalculatorFactory.java:5),玩家可在运行时用 =config new <类型> 切换。

MULTI(多类型值)后端规模远超其它四个(2415 行 vs 171–403 行),单独成页:多类型值系统。

基本信息

后端 工厂类 数值类型 文件行数
DOUBLE openmods.calc.types.fp.DoubleCalculatorFactory java.lang.Double 403
FRACTION openmods.calc.types.fraction.FractionCalculatorFactory org.apache.commons.lang3.math.Fraction 252
BIGINT openmods.calc.types.bigint.BigIntCalculatorFactory java.math.BigInteger 315
BOOL openmods.calc.types.bool.BoolCalculatorFactory java.lang.Boolean 171
MULTI openmods.calc.types.multi.TypedValueCalculatorFactory openmods.calc.types.multi.TypedValue 2415

枚举定义于 CalculatorType(src/main/java/openmods/calc/command/CalcState.java:120),各常量行号:DOUBLE :122、FRACTION :155、BIGINT :188、MULTI :221、BOOL :248。启动时的活动计算器为 DOUBLE(CalcState.java:265)。

功能

统一构建契约

SimpleCalculatorFactory<E, M>(SimpleCalculatorFactory.java:5)把构建过程固定为 5 步,子类只需覆写取空值、取值解析器、造打印器、配环境、配算符这几个钩子:

OperatorDictionary → configureOperators
Environment        → createStackManipulationFunctions(注入 swap/pop/dup)→ configureEnvironment
Compilers          → 由 ICompilerMapFactory 提供
IValuePrinter      → createValuePrinter

(SimpleCalculatorFactory.java:21-30)。注意 swap/pop/dup 三个栈函数在每个后端都无条件注入(.java:25),因此下表的内建符号计数不含它们。

内建符号与算符统计

后端 全局符号 二元算符 一元算符
DOUBLE 34 7 3
FRACTION 14 4 3
BIGINT 14(源码出现 15 次,见下) 11 4
BOOL 3 13 2
MULTI 66 30 6

统计方式:grep -c 'setGlobalSymbol(' / grep -c 'registerBinaryOperator(' / grep -c 'registerUnaryOperator('(types 目录下逐文件)。

DOUBLE — 浮点

全局符号 34 个(DoubleCalculatorFactory.java:42-287):

  • 常量:PI E INF MAX(:42-45,其中 MAX 绑定的是 Double.MIN_VALUE)
  • 一元数学:abs sgn sqrt ceil floor cos cosh sin sinh tan tanh acos acosh asin asinh atan atanh log10 ln exp rad deg
  • 二元数学:atan2 log(log 为二元,接受底数)
  • 聚合:min max sum avg(均基于 AccumulatorFunction,:224,232,240,248)
  • 随机:rand(:279)gauss(:287,高斯分布)

算符:一元 neg + -(:303,311,319),二元 + - * / % ^ **(:327,335,343,351,359,367,375)。

FRACTION — 精确有理数

全局符号 14 个(FractionCalculatorFactory.java):abs sgn numerator denominator frac int sqrt log min max sum avg rand gauss。

算符:一元 neg + -(:176,184,192),二元 + - * /(:200,208,216,224)。其中 * 通过 .setDefault() 设为默认二元算符(:222)。不提供 % ^ ** —— 与 DOUBLE 的显著差异。

BIGINT — 任意精度整数

全局符号源码出现 15 次、去重后仅 13 个:abs sgn min max sum avg gcd modpow get set clear flip rand。

差异成因:gcd 在 BigIntCalculatorFactory.java:98 与 :106 被连续注册两次,两处实现完全相同(均返回 left.gcd(right)),第二次覆盖第一次。这是一处真实的冗余注册,不是统计误差。

算符:一元 ~ neg + -(:174,182,190,198),二元 ^ | & + - * / % ** << >>(:206-286)。无浮点/三角函数。

优先级常量按运算类别分为 6 档(BigIntCalculatorFactory.java:165-170):PRIORITY_EXP=6 > PRIORITY_MULTIPLY=5 > PRIORITY_ADD=4 > PRIORITY_BITSHIFT=3 > PRIORITY_BITWISE=2 > PRIORITY_ASSIGN=1。

BOOL — 布尔逻辑

全局符号仅 3 个:true false rand。

算符 13 个二元 + 2 个一元(BoolCalculatorFactory.java:129-149),全部以多个别名指向同一实现:

实现类 别名 行
OpNot(一元) ~、not :130,131
OpXor ^、xor、!= :133,134,135
OpIff =、<=>、eq、iff :137,138,139,140
OpImplies =>、implies :142,143
OpOr ` 、or`
OpAnd &、and :148,149

即 6 个逻辑实现展开为 13 个二元 + 2 个一元算符名。= 在此处是等价(iff),与数学惯例不同。

数值

数值名 值
后端数 5(CalcState.java:122,155,188,221,248)
默认后端 DOUBLE(CalcState.java:265)
每后端无条件注入的栈函数 3(swap/pop/dup)
BIGINT 冗余注册符号 1(gcd,BigIntCalculatorFactory.java:98 与 :106)
BOOL 二元算符别名展开比 13 个算符名 / 6 个实现类

交互

后端本身无玩家交互。切换路径:

指令 行为
=config new double 新建 DOUBLE 计算器
=config new fraction 新建 FRACTION 计算器
=config new bigint 新建 BIGINT 计算器
=config new multi 新建 MULTI 计算器
=config new bool 新建 BOOL 计算器
=config store <名字> 给当前计算器命名
=config load <名字> 切换到已命名计算器
=config push / =config pop 计算器栈压入/弹出

合法类型取自 CalculatorType.values(),非法值抛 openmodslib.command.calc_invalid_type(CommandCalcFactory 中 config.new 分支)。

DOUBLE / FRACTION / BIGINT 三个数值后端还额外绑定 3 个游戏内坐标符号 _x / _y / _z,取自指令发送者的方块坐标(如 CalcState.java:128,136,144);MULTI 后端则绑定 player(CalcState.java:229)。所有后端都通过 SenderHolder.addPrinter 获得 p(打印)与 print(取值)两个输出符号(CalcState.java:78,101)。

相关条目