---
name: writing-hashql-jexpr
description: "HashQL J-Expr syntax for writing queries. Use when writing J-Expr code, using #literal/#struct/#list constructs, understanding function call syntax, or working with HashQL query files (.jsonc)."
license: AGPL-3.0
metadata:
  triggers:
    type: domain
    enforcement: suggest
    priority: high
    keywords:
      - J-Expr
      - jexpr
      - hashql query
      - hashql syntax
      - "#literal"
      - "#struct"
      - "#list"
      - "#tuple"
    intent-patterns:
      - "\\b(write|read|create|parse)\\b.*?\\b(j-?expr|hashql)\\b"
      - "\\b(hashql|jexpr)\\b.*?\\b(query|syntax|expression)\\b"
---

# Writing HashQL J-Expr

J-Expr is a JSON-based expression syntax for HashQL. It represents typed expressions using JSON primitives.

## Expression Types

J-Expr has three expression types:

| JSON Type | J-Expr Meaning                   |
| --------- | -------------------------------- |
| String    | Path/identifier/symbol           |
| Array     | Function call                    |
| Object    | Data constructor (with `#` keys) |

## Paths (Strings)

Strings are parsed as paths or identifiers:

```jsonc
"x"                           // Simple variable
"vertex.id.entity_id"         // Dotted path access
"::core::types::String"       // Namespaced/rooted path
"::graph::head::entities"     // Graph function path
```

## Function Calls (Arrays)

Arrays represent function calls: `[function, arg1, arg2, ...]`

```jsonc
// Basic function call
["add", {"#literal": 1}, {"#literal": 2}]

// Namespaced function
["::graph::head::entities", ["::graph::tmp::decision_time_now"]]

// Labeled argument with :prefix in object
["greet", {":name": {"#literal": "Alice"}}]

// Shorthand labeled argument (string with :prefix)
["func", ":name"]
```

## Data Constructors (Objects with # Keys)

Objects with special `#` keys construct data:

| Key        | Purpose               | Example                   |
| ---------- | --------------------- | ------------------------- |
| `#literal` | Primitive values      | `{"#literal": 42}`        |
| `#struct`  | Named fields          | `{"#struct": {"x": ...}}` |
| `#list`    | Variable-size ordered | `{"#list": [...]}`        |
| `#tuple`   | Fixed-size ordered    | `{"#tuple": [...]}`       |
| `#dict`    | Key-value map         | `{"#dict": {"k": ...}}`   |
| `#type`    | Type annotation       | Used with other keys      |

### Literals

```jsonc
{"#literal": 42}
{"#literal": "hello"}
{"#literal": true}
{"#literal": null}
{"#literal": 3.14, "#type": "Float"}
```

### Struct

```jsonc
{"#struct": {"name": {"#literal": "Alice"}, "age": {"#literal": 30}}}
{"#struct": {"x": {"#literal": 1}}, "#type": "Point"}
```

### List and Tuple

```jsonc
{"#list": [{"#literal": 1}, {"#literal": 2}]}
{"#tuple": [{"#literal": 1}, {"#literal": "text"}]}
```

### Dict

```jsonc
{ "#dict": { "key": { "#literal": "value" } } }
```

## Common Patterns

### Let Binding

```jsonc
["let", "varName", { "#literal": 10 }, ["add", "varName", { "#literal": 5 }]]
```

### Function Definition

```jsonc
["fn", {"#tuple": []}, {"#struct": {"vertex": "_"}}, "_", body_expr]
```

### Conditionals

```jsonc
["if", condition_expr, then_expr, else_expr]
```

### Comparison

```jsonc
["==", "left", "right"]
[">", {"#literal": 5}, {"#literal": 3}]
```

## Do

- Use `#literal` for all primitive values (numbers, strings, booleans, null)
- Use `::` prefix for namespaced paths
- Use `:` prefix for labeled arguments
- Combine `#type` with other constructors for type annotations

## Don't

- Don't use bare JSON numbers/booleans - wrap in `{"#literal": ...}`
- Don't confuse `#list` (variable-size) with `#tuple` (fixed-size)
- Don't use `#` prefix for labeled arguments (use `:`)
- Don't nest `#` keys incorrectly - each object should have one primary `#` key

## Examples

**Entity query:**

```jsonc
["::graph::head::entities", ["::graph::tmp::decision_time_now"]]
```

**Filtering with comparison:**

```jsonc
[
  "filter",
  "entities",
  [
    "fn",
    { "#tuple": [] },
    { "#struct": { "entity": "_" } },
    "_",
    ["==", "entity.draft_id", { "#literal": null }],
  ],
]
```

**Struct with type:**

```jsonc
{ "#struct": { "value": { "#literal": 100 } }, "#type": "Amount" }
```

## References

- [Syntax Reference](references/syntax-reference.md) - Paths, function calls, operators
- [Special Forms](references/special-forms.md) - Language constructs (`if`, `let`, `fn`, `type`, `use`, etc.)
- [Data Constructors](references/data-constructors.md) - Typed data (`#literal`, `#struct`, `#tuple`, `#list`, `#dict`, `#type`)
- [Type DSL](references/type-dsl.md) - Embedded type annotation syntax
- Parser: `libs/@local/hashql/syntax-jexpr/src/parser/`
- Object forms: `libs/@local/hashql/syntax-jexpr/src/parser/object/`
- Type DSL: `libs/@local/hashql/syntax-jexpr/src/parser/string/type.rs`
