one more bug, and documentation for infix
One error message gets a bit worse.
This commit is contained in:
parent
ba0c41673b
commit
6a65f6f233
|
@ -118,6 +118,65 @@ if (= 1 (% x 2))
|
|||
'even
|
||||
```
|
||||
|
||||
### Infix
|
||||
|
||||
The Mu shell supports infix operators:
|
||||
```
|
||||
3 + 1
|
||||
=> 4
|
||||
```
|
||||
|
||||
You don't need spaces around infix ops:
|
||||
```
|
||||
3+1
|
||||
=> 4
|
||||
```
|
||||
|
||||
Operator precedence is not hardcoded. Instead, there is just one rule:
|
||||
operators surrounded by whitespace have lower precedence than operators that
|
||||
are not.
|
||||
|
||||
To see how an expression is parsed, quote it:
|
||||
```
|
||||
'3+1
|
||||
=> (+ 3 1)
|
||||
```
|
||||
|
||||
You can create your own infix ops:
|
||||
```
|
||||
def (a <> b)
|
||||
(not (a = b))
|
||||
```
|
||||
|
||||
To permit arbitrary infix operators, the Mu shell partitions the space of
|
||||
graphemes between operators and regular symbols. As a result, you can't define
|
||||
symbols mixing the two.
|
||||
```
|
||||
'*global*
|
||||
=> ((* global) . *) # probably not what you want
|
||||
|
||||
'uppercase-char-p
|
||||
=> (- (- uppercase char) p) # probably not what you want
|
||||
|
||||
'(char> a p)
|
||||
=> ((char . >) a p) # probably not what you want
|
||||
```
|
||||
|
||||
Infix operators also work in prefix position:
|
||||
```
|
||||
(+ 3 1)
|
||||
=> 4
|
||||
```
|
||||
|
||||
To pass infix operators to higher-order functions, wrap them in parens. A
|
||||
silly example:
|
||||
```
|
||||
def (+++ x) # silly name
|
||||
x+1
|
||||
(map1 (+++) '(1 2 3))
|
||||
=> (2 3 4)
|
||||
```
|
||||
|
||||
### Known issues
|
||||
|
||||
* No mouse support.
|
||||
|
|
|
@ -392,6 +392,7 @@ fn test-infix {
|
|||
check-infix "(+a)", "((+ a))", "F - test-infix/unary-operator-3"
|
||||
check-infix "-a", "(- a)", "F - test-infix/unary-operator-4"
|
||||
check-infix "a+b", "(+ a b)", "F - test-infix/no-spaces"
|
||||
check-infix "3+1", "(+ 3 1)", "F - test-infix/no-spaces-starting-with-digit"
|
||||
check-infix "',a+b", "',(+ a b)", "F - test-infix/no-spaces-with-nested-quotes"
|
||||
check-infix "$a+b", "(+ $a b)", "F - test-infix/no-spaces-2"
|
||||
check-infix "-a+b", "(+ (- a) b)", "F - test-infix/unary-over-binary"
|
||||
|
@ -584,7 +585,7 @@ fn check-infix actual: (addr array byte), expected: (addr array byte), message:
|
|||
var actual-tree-ah/esi: (addr handle cell) <- address actual-tree-h
|
||||
read-cell actual-buffer, actual-tree-ah, trace
|
||||
#? dump-trace-with-label trace, "infix"
|
||||
#? dump-cell-from-cursor-over-full-screen actual-tree-ah, 7/fg 0/bg
|
||||
dump-cell-from-cursor-over-full-screen actual-tree-ah, 7/fg 0/bg
|
||||
var _actual-tree/eax: (addr cell) <- lookup *actual-tree-ah
|
||||
var actual-tree/esi: (addr cell) <- copy _actual-tree
|
||||
#
|
||||
|
|
|
@ -684,9 +684,9 @@ fn test-run-error-invalid-integer {
|
|||
#
|
||||
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 1/show-cursor
|
||||
# skip one line of padding
|
||||
check-screen-row screen, 1/y, " 1a ", "F - test-run-error-invalid-integer/0"
|
||||
check-screen-row screen, 2/y, " ... ", "F - test-run-error-invalid-integer/1"
|
||||
check-screen-row-in-color screen, 0xc/fg=error, 3/y, " invalid number ", "F - test-run-error-invalid-integer/2"
|
||||
check-screen-row screen, 1/y, " 1a ", "F - test-run-error-invalid-integer/0"
|
||||
check-screen-row screen, 2/y, " ... ", "F - test-run-error-invalid-integer/1"
|
||||
check-screen-row-in-color screen, 0xc/fg=error, 3/y, " unbound symbol: 1a ", "F - test-run-error-invalid-integer/2"
|
||||
}
|
||||
|
||||
fn test-run-error-unknown-symbol {
|
||||
|
|
|
@ -419,27 +419,6 @@ fn next-token in: (addr gap-buffer), out: (addr token), start-of-line?: boolean,
|
|||
next-stream-token in, out, trace
|
||||
break $next-token:case
|
||||
}
|
||||
# special-case: '-'
|
||||
{
|
||||
compare g, 0x2d/minus
|
||||
break-if-!=
|
||||
var dummy/eax: grapheme <- read-from-gap-buffer in # skip '-'
|
||||
var g2/eax: grapheme <- peek-from-gap-buffer in
|
||||
put-back-from-gap-buffer in
|
||||
var digit?/eax: boolean <- decimal-digit? g2
|
||||
compare digit?, 0/false
|
||||
break-if-=
|
||||
next-number-token in, out, trace
|
||||
break $next-token:case
|
||||
}
|
||||
# digit
|
||||
{
|
||||
var digit?/eax: boolean <- decimal-digit? g
|
||||
compare digit?, 0/false
|
||||
break-if-=
|
||||
next-number-token in, out, trace
|
||||
break $next-token:case
|
||||
}
|
||||
# other symbol char
|
||||
{
|
||||
var symbol?/eax: boolean <- symbol-grapheme? g
|
||||
|
@ -878,8 +857,22 @@ fn number-token? _self: (addr token) -> _/eax: boolean {
|
|||
break-if-!=
|
||||
g <- read-grapheme in-data
|
||||
}
|
||||
var result/eax: boolean <- decimal-digit? g
|
||||
return result
|
||||
{
|
||||
{
|
||||
var result/eax: boolean <- decimal-digit? g
|
||||
compare result, 0/false
|
||||
break-if-!=
|
||||
return 0/false
|
||||
}
|
||||
{
|
||||
var done?/eax: boolean <- stream-empty? in-data
|
||||
compare done?, 0/false
|
||||
}
|
||||
break-if-!=
|
||||
g <- read-grapheme in-data
|
||||
loop
|
||||
}
|
||||
return 1/true
|
||||
}
|
||||
|
||||
fn bracket-token? _self: (addr token) -> _/eax: boolean {
|
||||
|
|
Loading…
Reference in New Issue