Skip to content

Model json.loads for compile-time-constant string inputs #536

@khatchad

Description

@khatchad

Summary

tf.keras.Input(shape=json.loads("[32]")) produces a tensor whose dtype Ariadne resolves (FLOAT32, the Keras default) but whose shape it cannot trace (emits null dims, lattice ⊤ for shape). The shape information is recoverable in principle—json.loads("[32]") is a pure function on a compile-time-constant string, evaluable at analysis time.

Consider extending the analyzer to:

  • Recognize json.loads(s) where s is a string-literal argument.
  • Evaluate the parse at analysis time (Python's json.loads is deterministic on constant input).
  • Track the resulting list/dict structure through subsequent shape extractions.

This would let tf.keras.Input(shape=json.loads(...)) resolve to a concrete shape rather than fall back to ⊤.

Reproducer

import json
import tensorflow as tf

shape = json.loads("[32]")
x = tf.keras.Input(shape=shape)

Current output for x's inferred TensorType:

{TensorType(cellType="float32", dims=null)}

Expected after enhancement (modulo the batch-dimension convention tf.keras.Input already applies):

{TensorType(cellType="float32", dims=[SymbolicDim("?"), NumericDim(32)])}

Why It Matters

Precision wins. Downstream consumers (refactorings, type-inference pipelines) that drop ⊤ entries today would gain a concrete shape, reducing the "shape unknown" rate on real code. The enhancement does not change the lattice contract—shape-⊤ remains the correct fallback for genuinely opaque sources; this narrows the set of sources that count as opaque.

Scope

  • Limited to json.loads(s) where s is a compile-time string literal (CAst constant). Dynamic strings remain shape-⊤.
  • No need to model json.dumps or other JSON APIs—asymmetric use case (shape strings parsed in, rarely serialized out).
  • pickle.loads, ast.literal_eval, yaml.safe_load are similar candidates but out of scope; file separately if useful.

Cross-Refs

ponder-lab/Hybridize-Functions-Refactoring#491 tracks the consumer-side coordination: Hybridize currently uses json.loads("[32]") in a regression fixture to intentionally defeat shape inference and exercise the shape-⊤ branch. If this enhancement lands, that fixture needs a replacement (a more durable opaque-shape source) before bumping the Ariadne dep.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions