# UNLESS

Exception clause operator. Syntactic sugar for `AND NOT` with precedence lower than OR, designed to express legal exceptions naturally.

## Syntax

```l4
condition UNLESS exception
```

## Semantics

`A UNLESS B` is equivalent to `A AND NOT B`

```l4
-- These are equivalent:
x UNLESS y
x AND NOT y
```

## Precedence

**Key Feature:** UNLESS binds _looser_ than both AND and OR. This makes it act as an exception to the entire preceding expression:

```l4
-- UNLESS applies to the ENTIRE preceding expression:
A AND B AND C UNLESS D  ≡  (A AND B AND C) AND NOT D
A OR B OR C UNLESS D    ≡  (A OR B OR C) AND NOT D

-- NOT like this (which would happen with higher precedence):
-- A OR B UNLESS C  ≠  A OR (B AND NOT C)
```

## Examples

**Example file:** 

```l4-file
-- UNLESS Keyword Examples
-- UNLESS is syntactic sugar for AND NOT, with precedence lower than OR.

--------------------------------------------------------------------------------
-- Basic UNLESS Tests
--------------------------------------------------------------------------------

-- TRUE UNLESS TRUE = TRUE AND NOT TRUE = FALSE
DECIDE basic1 IF TRUE UNLESS TRUE
#ASSERT NOT basic1

-- TRUE UNLESS FALSE = TRUE AND NOT FALSE = TRUE
DECIDE basic2 IF TRUE UNLESS FALSE
#ASSERT basic2

-- FALSE UNLESS TRUE = FALSE AND NOT TRUE = FALSE
DECIDE basic3 IF FALSE UNLESS TRUE
#ASSERT NOT basic3

-- FALSE UNLESS FALSE = FALSE AND NOT FALSE = FALSE
DECIDE basic4 IF FALSE UNLESS FALSE
#ASSERT NOT basic4

--------------------------------------------------------------------------------
-- Legal Exception Pattern
--------------------------------------------------------------------------------

-- "The applicant is eligible if they meet all requirements,
--  UNLESS they have been disqualified"

ASSUME `is a citizen` IS A BOOLEAN
ASSUME `has resided for 5 years` IS A BOOLEAN
ASSUME `has valid identification` IS A BOOLEAN
ASSUME `has been disqualified` IS A BOOLEAN

DECIDE `is eligible for benefits` IF
      `is a citizen`
  AND `has resided for 5 years`
  AND `has valid identification`
  UNLESS `has been disqualified`

--------------------------------------------------------------------------------
-- UNLESS with AND (multi-line)
--------------------------------------------------------------------------------

-- All conditions must be true, unless the exception applies
DECIDE and_unless_example IF
         TRUE
  AND    TRUE
  AND    TRUE
  UNLESS TRUE

#ASSERT NOT and_unless_example  -- (T AND T AND T) AND NOT T = FALSE

DECIDE and_unless_example2 IF
         TRUE
  AND    TRUE
  AND    TRUE
  UNLESS FALSE

#ASSERT and_unless_example2  -- (T AND T AND T) AND NOT F = TRUE

--------------------------------------------------------------------------------
-- UNLESS with OR (demonstrates precedence)
--------------------------------------------------------------------------------

-- UNLESS binds LOOSER than OR, so:
-- (FALSE OR TRUE OR TRUE) UNLESS TRUE = (TRUE) AND NOT TRUE = FALSE

DECIDE or_unless_example IF
         FALSE
  OR     TRUE
  OR     TRUE
  UNLESS TRUE

#ASSERT NOT or_unless_example

-- Another OR example
DECIDE or_unless_example2 IF
         FALSE
  OR     TRUE
  UNLESS FALSE

#ASSERT or_unless_example2  -- (FALSE OR TRUE) AND NOT FALSE = TRUE

--------------------------------------------------------------------------------
-- Single-line variants (same semantics)
--------------------------------------------------------------------------------

DECIDE single_and IF TRUE AND TRUE AND TRUE UNLESS TRUE
DECIDE single_or IF FALSE OR TRUE OR TRUE UNLESS TRUE

#ASSERT NOT single_and
#ASSERT NOT single_or

--------------------------------------------------------------------------------
-- Precedence Verification
--------------------------------------------------------------------------------

-- This test proves UNLESS binds looser than OR:
-- If UNLESS bound tighter: TRUE OR FALSE UNLESS TRUE = TRUE OR (FALSE AND NOT TRUE) = TRUE
-- With correct precedence: TRUE OR FALSE UNLESS TRUE = (TRUE OR FALSE) AND NOT TRUE = FALSE

DECIDE precedence_test IF TRUE OR FALSE UNLESS TRUE
#ASSERT NOT precedence_test  -- Proves UNLESS binds looser than OR

--------------------------------------------------------------------------------
-- Real-world Legal Examples
--------------------------------------------------------------------------------

-- Contract validity
ASSUME `signed by both parties` IS A BOOLEAN
ASSUME `consideration exchanged` IS A BOOLEAN
ASSUME `signed under duress` IS A BOOLEAN

DECIDE `contract is valid` IF
      `signed by both parties`
  AND `consideration exchanged`
  UNLESS `signed under duress`

-- Building access
ASSUME `has valid badge` IS A BOOLEAN
ASSUME `during business hours` IS A BOOLEAN
ASSUME `building is closed` IS A BOOLEAN

DECIDE `can enter building` IF
      `has valid badge`
  AND `during business hours`
  UNLESS `building is closed`

-- Employment eligibility
ASSUME `is employee` IS A BOOLEAN
ASSUME `is contractor` IS A BOOLEAN
ASSUME `has been terminated` IS A BOOLEAN

DECIDE `has system access` IF
         `is employee`
  OR     `is contractor`
  UNLESS `has been terminated`
```



### Basic Usage

```l4
-- Simple exception
DECIDE result IF TRUE UNLESS FALSE
#ASSERT result  -- TRUE AND NOT FALSE = TRUE

DECIDE blocked IF TRUE UNLESS TRUE
#ASSERT NOT blocked  -- TRUE AND NOT TRUE = FALSE
```

### Legal Exception Pattern

```l4
-- "The applicant is eligible if they are a citizen
--  and have resided for 5 years, UNLESS they have been disqualified"

ASSUME `is a citizen` IS A BOOLEAN
ASSUME `has resided for 5 years` IS A BOOLEAN
ASSUME `has been disqualified` IS A BOOLEAN

DECIDE `is eligible` IF
      `is a citizen`
  AND `has resided for 5 years`
  UNLESS `has been disqualified`
```

This reads naturally and correctly evaluates as:

```
(is a citizen AND has resided for 5 years) AND NOT has been disqualified
```

### Multi-line Format

UNLESS works well with L4's layout-sensitive syntax:

```l4
DECIDE `can enter premises` IF
         `has valid badge`
  AND    `during business hours`
  AND    `not on restricted list`
  UNLESS `building is closed`
```

### With OR Conditions

UNLESS applies to the entire OR expression:

```l4
-- "Eligible if employee OR contractor, UNLESS terminated"
DECIDE `has access` IF
         `is employee`
  OR     `is contractor`
  UNLESS `has been terminated`

-- Evaluates as: (is employee OR is contractor) AND NOT has been terminated
```

## Why UNLESS?

### Natural Legal Language

Legal text commonly uses "unless" to express exceptions:

- "The contract is valid **unless** signed under duress"
- "Benefits apply **unless** the applicant has been disqualified"
- "Access is permitted **unless** revoked by administrator"

### Avoids Parentheses

Without UNLESS, you'd need explicit grouping:

```l4
-- Without UNLESS (requires parentheses):
DECIDE eligible IF (condA AND condB AND condC) AND NOT exception

-- With UNLESS (reads naturally):
DECIDE eligible IF condA AND condB AND condC UNLESS exception
```

### Correct Precedence by Default

If UNLESS had normal AND-level precedence, this common pattern would break:

```l4
-- If UNLESS bound like AND, this would be WRONG:
A OR B UNLESS C  would mean  A OR (B AND NOT C)  -- WRONG!

-- With correct low precedence:
A OR B UNLESS C  means  (A OR B) AND NOT C  -- CORRECT!
```

## Truth Table

| A     | B     | A UNLESS B |
| ----- | ----- | ---------- |
| TRUE  | TRUE  | FALSE      |
| TRUE  | FALSE | TRUE       |
| FALSE | TRUE  | FALSE      |
| FALSE | FALSE | FALSE      |

## Comparison with AND NOT

| Expression          | Equivalent To         | Result  |
| ------------------- | --------------------- | ------- |
| `TRUE UNLESS TRUE`  | `TRUE AND NOT TRUE`   | FALSE   |
| `TRUE UNLESS FALSE` | `TRUE AND NOT FALSE`  | TRUE    |
| `A OR B UNLESS C`   | `(A OR B) AND NOT C`  | depends |
| `A AND B UNLESS C`  | `(A AND B) AND NOT C` | depends |

## Related Keywords

- **[AND](/l4/reference/operators/AND.md)** - Logical conjunction
- **[OR](/l4/reference/operators/OR.md)** - Logical disjunction
- **[NOT](/l4/reference/operators/NOT.md)** - Logical negation
- **[IMPLIES](/l4/reference/operators/IMPLIES.md)** - Logical implication

## See Also

- **[Operators Reference](/l4/reference/operators.md)** - All operators
- **[Logical Operators](/l4/reference/operators.md#logical-operators)** - Boolean operations
