Skip to content

Add evaluate_expression entrypoint#25

Merged
jcschaff merged 2 commits into
mainfrom
add-evaluate-expression
Jul 18, 2026
Merged

Add evaluate_expression entrypoint#25
jcschaff merged 2 commits into
mainfrom
add-evaluate-expression

Conversation

@jcschaff

Copy link
Copy Markdown
Member

Summary

Adds evaluate_expression: evaluate a native-syntax VCell infix expression against a {symbol: value} table and get a 64-bit float back — or a structured error.

from libvcell import evaluate_expression, VCellExpressionError

evaluate_expression("a + b/c", {"a": 10.0, "b": 20.0, "c": 5.0})  # -> 14.0
evaluate_expression("2 + 3*sqrt(4)", {})                          # -> 8.0

try:
    evaluate_expression("1/c", {"c": 0.0})
except VCellExpressionError as e:
    e.error_type   # "DivideByZeroException"

Design

  • Structured boundary object EvalReturnValue(success, value, error_type, message) mirrors the existing ReturnValue. The native entry point always returns a JSON document; Python parses it into EvalReturnValue.
  • Two layers: native_calls.evaluate_expression returns the raw EvalReturnValue (branch on .success); the public model_utils.evaluate_expression returns the float or raises VCellExpressionError (carrying .error_type + .message).
  • Evaluation uses vcell-core's Expression: parse → bindExpression(new SimpleSymbolTable(names))evaluateVector(values). SimpleSymbolTable gives the lightweight dummy binding — no VCell model / MathDescription needed. Any symbol the expression references must be supplied; extras are ignored.
  • Non-finite results (Inf/NaN, unrepresentable in JSON) are surfaced as an error.

Changes

Java (vcell-native/): ModelUtils.evaluateExpression, Entrypoints.evaluateExpression @CEntryPoint (JSON in/out), MainRecorder exercise, 7 JVM tests.
Python (libvcell/): native_utils (hasattr-guarded registration), native_calls (EvalReturnValue + call), model_utils (evaluate_expression + VCellExpressionError), exported from __init__; Python tests.
Docs: new docs/design.md (architecture, FFI conventions, entry-point catalog, evaluate_expression, how-to-add-an-entrypoint) + mkdocs nav + API reference. Also ignore stray uv.lock (project uses Poetry).

Verification

  • Java: 30/30 tests pass (7 new — value, constant, extra-symbols, unbound → ExpressionBindingException, parse error, divide-by-zero → DivideByZeroException, domain → FunctionDomainException).
  • Local native rebuild + full Python suite 19/19 pass (the 8 evaluate_expression tests run against the rebuilt dylib, incl. pytest.raises(VCellExpressionError) with expected error_type).
  • make check green (ruff, prettier incl. docs, mypy strict, deptry).

🤖 Generated with Claude Code

jcschaff and others added 2 commits July 18, 2026 15:18
Evaluates a native-syntax VCell infix expression against a JSON {name: value}
symbol table, returning a 64-bit float (or a structured error).

Java (vcell-native):
- ModelUtils.evaluateExpression(String, Map<String,Double>): parse -> bind to a
  SimpleSymbolTable built from the supplied names -> evaluateVector. Any symbol
  the expression references must be supplied; extras are ignored.
- Entrypoints.evaluateExpression @centrypoint: parses the symbol-table JSON,
  evaluates, and returns a JSON document
  {"success":true,"value":<double>} or
  {"success":false,"error_type":<exceptionClass>,"message":<text>}.
  Non-finite results are surfaced as an error (JSON can't encode Inf/NaN).
- MainRecorder exercises the path so native-image records its config.

Python (libvcell):
- native_utils registers evaluateExpression (hasattr-guarded for older libs).
- native_calls.evaluate_expression returns the structured EvalReturnValue
  (success/value/error_type/message).
- model_utils.evaluate_expression returns float or raises VCellExpressionError
  (carrying error_type + message); both exported from __init__.

Tests:
- Java: 7 ModelEntrypointsTest cases (value, constant, extra-symbols, unbound,
  parse error, divide-by-zero, domain error) - all pass on the JVM.
- Python: raise/return tests, skipped until the native lib is rebuilt.

Docs: new docs/design.md (architecture, FFI conventions, entry-point catalog,
evaluate_expression, how-to-add-an-entrypoint); referenced in mkdocs nav and
the module API reference. Also ignore stray uv.lock (project uses Poetry).

The Python end-to-end path requires rebuilding the native shared library
(scripts/local_build_native.sh) to expose the new C entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Release that adds the evaluate_expression entrypoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jcschaff
jcschaff merged commit 2f83614 into main Jul 18, 2026
5 checks passed
@jcschaff
jcschaff deleted the add-evaluate-expression branch July 18, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant