not is a prefix word in .fln, looser than comparisons and tighter than and, with not(x) still a call

This commit is contained in:
Joseph Ferano 2026-09-26 06:18:11 +07:00
parent 06eaf738b9
commit 6e006fce27
3 changed files with 17 additions and 4 deletions

View File

@ -662,10 +662,6 @@ In a .fln buffer, ~if and(state.paused|)~ then RET leaves ~)~ at the ~if~'s colu
the next argument cannot be typed where it belongs. A line inside open brackets,
closer-led or not, goes to the continuation column (aligned after the opening bracket).
** NEXT not is a prefix word
Decided 2026-09-26: .fln writes ~not x~ (binding like F#'s ~not~, tighter than
~and~/~or~, looser than comparisons); ~not(x)~ keeps working as a call.
** NEXT A let takes several bindings on indented lines
Decided 2026-09-26: lines indented under a ~let~ that are ~name = v~ or ~name: T = v~ are
more bindings of the same let; anything else there stays refused. flan convert writes

View File

@ -173,6 +173,8 @@ Each item: the proposal, then the reason in one line.
`.init-once.counter`; rename it. **Built**, without the rename: it prints and
reads back through the fallback, `defonce(.init-once.counter, i64, 7)`.
- **`and`, `or`, `not` are words**, since they are Flan's own names. **Built.**
`not` is a prefix word: `not a == b` is `not (a == b)`, `not a and b` is
`(not a) and b`, and `not(x)`, glued, is the call.
- **Casts and type-taking builtins are calls:** `i32(x)`, `vec-new(u8)`,
`max-value(u8)`, `the([3 f32], [1 2 3.5])`. A pointer cast is the type
called: `Ptr(Color)(p)` reads `((Ptr Color) p)`. **Built.**

View File

@ -524,6 +524,15 @@ let () =
reads "chain" "x = a < b < c" "(set x (< a b c))";
reads "left to right" "x = a - b + c" "(set x (+ (- a b) c))";
reads "precedence" "x = a or b and not c == d" "(set x (or a (and b (not (= c d)))))";
(* not is a prefix word, between and and the comparisons. *)
reads "not over a comparison" "x = not a == b" "(set x (not (= a b)))";
reads "not under and" "x = not a and b" "(set x (and (not a) b))";
reads "not twice" "x = not not a" "(set x (not (not a)))";
reads "not of a group" "x = not (a or b)" "(set x (not (or a b)))";
reads "not glued is a call" "x = not(a) or b" "(set x (or (not a) b))";
reads "not as a statement" "if not done\n go()" "(when (not done) (go))";
refuses "not after a comparison" "x = a == not b" "indent/operator-operand" "nothing is on its left";
refuses "not in a spaced vector" "x = [not a b]" "indent/separate-elements" "commas";
refuses "not-equal chain" "x = a != b != c" "indent/chained-not-equal" "!=(a, b, c)";
reads "not-equal call" "x = !=(a, b, c)" "(set x (!= a b c))";
refuses "mixed comparison" "x = a < b <= c" "indent/mixed-comparison" "and";
@ -742,6 +751,12 @@ let () =
| exception e -> fail "%s: %s" name (diag_text e)
in
prints "compound assignment" "(defn f [] () (set x (+ x 1)))" " x += 1";
prints "not as a word" "(defn f [] () (g (not (= a b)) (and (not x) y)))"
"g(not a == b, not x and y)";
prints "not of a lower operator in parentheses" "(defn f [] () (g (not (or a b))))"
"g(not (a or b))";
prints "not under a comparison in parentheses" "(defn f [] () (g (= (not a) b)))"
"g((not a) == b)";
prints "compound update" "(defn f [] () (update (at a (next)) + 1))"
" a[next()] += 1";
prints "arm statements" "(defn f [] () (match s 1 (break) _ (return 2)))"