Skip to content

Compiler does not support BigDecimal/BigInteger in compiled expression path #544

@lukaszlenart

Description

@lukaszlenart

Problem

The expression compiler generates Java source code (via javassist) that uses raw Java operators (+, -, *, /, ~, <<, >>) for arithmetic and bitwise operations. This works for primitives but fails for BigDecimal and BigInteger objects, since Java does not support operator overloading.

Additionally, there are minor type-handling gaps for Float widening, instanceof compilation, and method calls on auto-boxed primitives.

Documented by

PR #543 added 11 @Disabled dual-mode tests that document these divergences between interpreted and compiled paths:

Category Tests Root cause
BigDecimal arithmetic (-1b, +1b, 2*2.0b, etc.) 8 Operators can't apply to BigDecimal objects
BigInteger arithmetic (-1h, +1H, 2h*2, etc.) 7 Operators can't apply to BigInteger objects
BigInteger bitwise (~1h, 5h<<2, 5h>>2) 3 Same fundamental issue
Float widening (5f-2F) 1 coerceToNumeric doesn't distinguish Float from Double
instanceof (5 instanceof java.lang.Integer) 2 Generated source has syntax errors
Method on auto-boxed primitive (index.toString()) 1 Missing boxing in generated source

Suggested approach

BigDecimal/BigInteger (18 tests) — main effort

  1. NumericExpression.toGetSourceString() should detect when getterClass is BigDecimal/BigInteger and generate ognl.OgnlOps.add(a, b) instead of a + b
  2. NumericExpression.coerceToNumeric() line 85 strips type info from ASTConst children via value.toString() — needs to preserve BigDecimal/BigInteger construction
  3. ASTNegate.toGetSourceString() should generate ognl.OgnlOps.negate(a) instead of -a
  4. ASTBitNegate similarly needs ognl.OgnlOps.bitNegate(a)
  5. ASTConst.toGetSourceString() needs to emit new java.math.BigDecimal("value") / new java.math.BigInteger("value")

The OgnlOps methods (add, subtract, multiply, divide, negate, bitNegate, remainder) already handle BigDecimal/BigInteger correctly — they're what the interpreted path uses.

Float widening (1 test)

OgnlRuntime.getNumericLiteral() likely returns the same suffix for Float and Double. Needs a Float-specific "f" literal path in coerceToNumeric.

instanceof (2 tests)

ASTInstanceof.toGetSourceString() generates source that javassist can't parse ("missing member name"). Investigate generated output and fix syntax, or delegate to a runtime helper.

Method on auto-boxed primitive (1 test)

ASTMethod compilation for index.toString() fails because index returns int (primitive) and the compiler calls .toString() without boxing. Needs Integer.valueOf(...) wrapping in generated source.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions