Friendly language syntax #29

Closed
opened 2024-08-20 20:38:12 +02:00 by liquidev · 0 comments
liquidev commented 2024-08-20 20:38:12 +02:00 (Migrated from github.com)

I've been wondering about a syntax friendlier than S-expressions lately.

Style

  • We use camelCase because it's the quickest to type while separating words somewhat. It's not lossless like kebab-case though, which is annoying, but we wouldn't want to be slowing down users with having to hold Shift to type _, and - likewise conflicts with this goal (because you can't do (or even fat-finger) x-y.)
  • We use two spaces instead of four, because our horizontal screen real estate is limited.

Comments

Lua or Haskell, pick your poison.

-- This is a comment

Rationale: I don't think // or ; would fit the rest of the syntax very well, and I'd like # for hex RGB(A) literals.

Literals

Numbers stay the same, bools are now capitalized.

()
123
False
True

I'll get to why bools get capitalized now later.

Operators

We now have infix operators.

For now to keep scope down (also we don't have system functions for anything else) we'll have the standard ones:

  • + addition
  • - subtraction and negation
  • * multiplication
  • / division
  • ==, != (to replace = and <>), <, <=, >, >=
  • ! for inverting a bool
  • and and or for boolean AND and OR

Operators may be followed by, but not preceded by newlines.

Lambdas

Roc-inspired:

\x, y -> x + y

Zero arguments is not possible with this syntax; a dummy () may be passed instead.

\_ -> 123

Calling a lambda does not use any additional delimiters.

someFunction argument1 argument2
noArguments () -- actually one argument

Arguments may not span multiple lines. If you find yourself having that many arguments, consider packing them into a data structure for readability.

Conditionals

For now we'll stick with the existing if, to be replaced with a pattern-matching construct later.

-- Parentheses are required for separating the result expression from the condition
if (condition)
  thenThis
else
  whateverElse

Defs

Using a plain = because it's the shortest.

fib = \n ->
  if (n < 2)
    n
  else
    (fib (n - 1)) + (fib (n - 2))

Defs are still only allowed before the trailing result expression.

x = 1
y = 2

thisIsTheResult

-- not allowed
-- z = 3

Lets

Syntax is similar to ML, but the in is replaced with a newline.

let x = 1
let y = 2
x + y

If you want multiple lines, wrap your expression in parentheses.

let x = (
  longArgument +
  longArgument
)
x + 10

Lists

Instead of the list function, you now construct lists using brackets [].

[1, 2]

Newline can serve as an additional separator over commas.

[
  1
  2
]

This should make it less annoying to add stuff in the middle of lists or rearrange it, since haku will make some pretty big use of lists for composing scribbles together.

New: tags

Identifiers starting with an uppercase letter are literal tags, which will become useful for representing enums etc. Here are some ideas I had today:

blendMode Replace (fillRect rect #0000)
shortcut (Ctrl V) paste

Note how tags can be called just like functions - this allows them to carry a payload (as is the case in that Ctrl V example.)

New: colors

rgba colors can be more easily represented using #RRGGBBAA, #RRGGBB, #RGBA, or #RGB syntax. When A is omitted, it defaults to FF. This will help with pasting colors from outside pickers.

Example

Here's something I sketched up today with ideas from #12.

withRect \rect ->
fillRect rect #000
-- A simple brush demonstrating how to use withRect and editRect together for selecting and editing a rectangle.
-- This brush is a basic selection - it can select a piece of the wall, move it elsewhere, and you can even paste something onto the canvas.

lift = \pixmap, rect ->
  [
    fillRect rect #000
    editRect rect \rect ->
      blit pixmap rect
    -- I'm yet to come up with a counterexample for separating list elements with newlines here
  ]

[
  withRect \rect ->
    let pixmap = capture rect
    [
      fillRect rect #000
      lift pixmap rect
    ]

  shortcut (Ctrl V) \_ ->
    getClipboard Pixmap \pixmap ->
    lift pixmap (screenCenteredRect pixmap.size)
]
I've been wondering about a syntax friendlier than S-expressions lately. ### Style - We use `camelCase` because it's the quickest to type while separating words somewhat. It's not lossless like `kebab-case` though, which is annoying, but we wouldn't want to be slowing down users with having to hold <kbd>Shift</kbd> to type `_`, and `-` likewise conflicts with this goal (because you can't do (or even fat-finger) `x-y`.) - We use two spaces instead of four, because our horizontal screen real estate is limited. ### Comments Lua or Haskell, pick your poison. ``` -- This is a comment ``` Rationale: I don't think `//` or `;` would fit the rest of the syntax very well, and I'd like `#` for hex RGB(A) literals. ### Literals Numbers stay the same, bools are now capitalized. ```haku () 123 False True ``` I'll get to why bools get capitalized now later. ### Operators We now have infix operators. For now to keep scope down (also we don't have system functions for anything else) we'll have the standard ones: - `+` addition - `-` subtraction and negation - `*` multiplication - `/` division - `==`, `!=` (to replace `=` and `<>`), `<`, `<=`, `>`, `>=` - `!` for inverting a bool - `and` and `or` for boolean AND and OR Operators may be followed by, but not preceded by newlines. ### Lambdas Roc-inspired: ```haku \x, y -> x + y ``` Zero arguments is not possible with this syntax; a dummy `()` may be passed instead. ```haku \_ -> 123 ``` Calling a lambda does not use any additional delimiters. ```haku someFunction argument1 argument2 noArguments () -- actually one argument ``` Arguments may not span multiple lines. If you find yourself having that many arguments, consider packing them into a data structure for readability. ### Conditionals For now we'll stick with the existing `if`, to be replaced with a pattern-matching construct later. ```haku -- Parentheses are required for separating the result expression from the condition if (condition) thenThis else whateverElse ``` ### Defs Using a plain `=` because it's the shortest. ```haku fib = \n -> if (n < 2) n else (fib (n - 1)) + (fib (n - 2)) ``` Defs are still only allowed before the trailing result expression. ```haku x = 1 y = 2 thisIsTheResult -- not allowed -- z = 3 ``` ### Lets Syntax is similar to ML, but the `in` is replaced with a newline. ```haku let x = 1 let y = 2 x + y ``` If you want multiple lines, wrap your expression in parentheses. ```haku let x = ( longArgument + longArgument ) x + 10 ``` ### Lists Instead of the `list` function, you now construct lists using brackets `[]`. ```haku [1, 2] ``` Newline can serve as an additional separator over commas. ```haku [ 1 2 ] ``` This should make it less annoying to add stuff in the middle of lists or rearrange it, since haku will make some pretty big use of lists for composing scribbles together. ### New: tags Identifiers starting with an uppercase letter are _literal tags_, which will become useful for representing enums etc. Here are some ideas I had today: ```haku blendMode Replace (fillRect rect #0000) shortcut (Ctrl V) paste ``` Note how tags can be called just like functions - this allows them to carry a payload (as is the case in that `Ctrl V` example.) ### New: colors `rgba` colors can be more easily represented using `#RRGGBBAA`, `#RRGGBB`, `#RGBA`, or `#RGB` syntax. When `A` is omitted, it defaults to `FF`. This will help with pasting colors from outside pickers. ## Example Here's something I sketched up today with ideas from #12. ```haku withRect \rect -> fillRect rect #000 ``` ``` -- A simple brush demonstrating how to use withRect and editRect together for selecting and editing a rectangle. -- This brush is a basic selection - it can select a piece of the wall, move it elsewhere, and you can even paste something onto the canvas. lift = \pixmap, rect -> [ fillRect rect #000 editRect rect \rect -> blit pixmap rect -- I'm yet to come up with a counterexample for separating list elements with newlines here ] [ withRect \rect -> let pixmap = capture rect [ fillRect rect #000 lift pixmap rect ] shortcut (Ctrl V) \_ -> getClipboard Pixmap \pixmap -> lift pixmap (screenCenteredRect pixmap.size) ] ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: liquidex/rkgk#29
No description provided.