Skip to content

Implement unary negation expressions #38

Description

@Seddryck

Description

Implement unary negation as first-class expression syntax.

The current Expressif parser recognizes ! as a unary predication operator. The Tree-sitter grammar should preserve that surface syntax explicitly instead of translating it into semantic predicate behavior during parsing.

Examples:

!less-than(5)
!is-null
!foo(@value)

The parser must recognize structure only. Whether the operand is semantically usable as a predicate belongs to the binding layer.

Syntax model

Add a dedicated unary expression node:

ExpressionSyntax
└── UnaryExpressionSyntax
    ├── operator: UnaryOperatorSyntax
    └── operand: ExpressionSyntax

Initially the unary operator is:

!

The CST should preserve the operator token and operand explicitly.

For example:

!less-than(5)

should conceptually produce:

UnaryExpressionSyntax
├── operator: !
└── operand
    └── FunctionCallSyntax("less-than")
        └── NumericLiteralSyntax("5")

Generic operand syntax

Unary negation should reuse the ordinary expression grammar rather than a predicate-specific grammar.

Examples that are syntactically valid include:

!less-than(5)
!is-null
!unknown(5)
!$0
!.active

The parser must not determine whether unknown(5), $0, or .active actually evaluate to a boolean/predicate-compatible result.

Composition

Unary expressions should compose naturally with expression contexts supported by the grammar.

Examples:

foo(!less-than(5))
!less-than(5) | some-function

If repeated negation is structurally valid, the grammar should preserve it recursively:

!!is-null

as nested UnaryExpressionSyntax nodes.

Whitespace

Whitespace around the complete expression is insignificant.

Whether whitespace between ! and its operand is accepted should follow the established operator-token rules, but the CST must preserve the same expression structure.

Examples to cover:

!is-null
! less-than(5)

if both are deliberately supported by the grammar.

Out of scope

Do not implement or special-case:

  • predicate/function catalogue lookup;
  • validation that the operand returns a boolean;
  • boolean evaluation semantics;
  • binary operators;
  • grouped logical expressions;
  • semantic lowering.

Tests

Add Tree-sitter corpus tests covering at minimum:

  • negation of a zero-argument function;
  • negation of a function with arguments;
  • negation of references/shorthands once available;
  • nested negation;
  • use as a function argument;
  • surrounding whitespace;
  • malformed ! without an operand;
  • CST structure preserving the unary operator.

Tests should assert CST structure, not only parse success.

Architectural constraint

! is syntax, not proof that its operand is a predicate.

The syntax parser must remain independent from the function catalogue and semantic type system. Predicate compatibility belongs to binding/validation.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions