mirror of
https://github.com/exoticorn/curlywas.git
synced 2026-01-20 11:46:43 +01:00
add some docs, allow leading zeros in literals
This commit is contained in:
29
README.md
29
README.md
@@ -89,16 +89,25 @@ For floating point numbers, only the most basic decimal format is currently impl
|
|||||||
0.464, 3.141, -10.0
|
0.464, 3.141, -10.0
|
||||||
```
|
```
|
||||||
|
|
||||||
String literals exist in a very basic form. No escape character implemented yet.
|
String literals are used for include paths, import names and as literal strings in the data section. The following escapes are supported:
|
||||||
|
| Escape | Result | Comment |
|
||||||
|
| `\"` | `"` | |
|
||||||
|
| `\'` | `'` | |
|
||||||
|
| `\t` | 8 | |
|
||||||
|
| `\n` | 10 | |
|
||||||
|
| `\r` | 13 | |
|
||||||
|
| `\N` | 0x0N | (Can't be followed by a hex digit) |
|
||||||
|
| `\NN` | 0xNN | |
|
||||||
|
|
||||||
```
|
```
|
||||||
"env.memory", "Hello World!"
|
"env.memory", "Hello World!"
|
||||||
|
|
||||||
this does not work, yet:
|
|
||||||
|
|
||||||
"one line\nsecond line", "They said: \"Enough!\""
|
"one line\nsecond line", "They said: \"Enough!\""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Character literals are enclosed in single quotes `'` and support the same escapes as strings. They can contain up to 4 characters and evaluate to the
|
||||||
|
little-endian representation of these characters. For examples: `'A'` evaluates to `0x41`, `'hi'` evaluates to 0x6968, and `'Crly'` to 0x7a6c7243.
|
||||||
|
|
||||||
### Imports
|
### Imports
|
||||||
|
|
||||||
WebAssembly imports are specified with a module and a name. In CurlyWas you give them inside a single string literal, seperated by a dot. So a module `env` and name `printString` would be written `"env.printString"`.
|
WebAssembly imports are specified with a module and a name. In CurlyWas you give them inside a single string literal, seperated by a dot. So a module `env` and name `printString` would be written `"env.printString"`.
|
||||||
@@ -295,6 +304,9 @@ So for example this block evaluates to 12:
|
|||||||
|
|
||||||
Blocks are used as function bodies and in flow control (`if`, `block`, `loop`), but can also used at any point inside an expression.
|
Blocks are used as function bodies and in flow control (`if`, `block`, `loop`), but can also used at any point inside an expression.
|
||||||
|
|
||||||
|
Variable re-assignments of the form `name = name <op> expression` can be shortened to `name <op>= expression`, for example `x += 1` to increment `x` by one. This works for all arithmetic, bit and shift operators.
|
||||||
|
The same is allowed for `name := name <op> expression`, ie. `x +:= 1` increments `x` and returns the new value.
|
||||||
|
|
||||||
#### Flow control
|
#### Flow control
|
||||||
|
|
||||||
`if condition_expression { if_true_block } [else {if_false_block}]` executes the `if_true_block` if the condition evaluates to a non-zero integer and
|
`if condition_expression { if_true_block } [else {if_false_block}]` executes the `if_true_block` if the condition evaluates to a non-zero integer and
|
||||||
@@ -304,6 +316,17 @@ the `if_false_block` otherwise (if it exists). It can also be used as an express
|
|||||||
let a = if 0 { 2 } else { 3 }; // assigns 3 to a
|
let a = if 0 { 2 } else { 3 }; // assigns 3 to a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the `if_false_block` contains exactly one `if` expression or statement you may omit the curly braces, writing `else if` chains like:
|
||||||
|
```
|
||||||
|
if x == 0 {
|
||||||
|
doOneThing()
|
||||||
|
} else if x == 1 {
|
||||||
|
doThatOtherThing()
|
||||||
|
} else {
|
||||||
|
keepWaiting()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
`block name { ... }` opens a named block scope. A branch statement can be used to jump to the end of the block. Currently, `block` can only be used
|
`block name { ... }` opens a named block scope. A branch statement can be used to jump to the end of the block. Currently, `block` can only be used
|
||||||
as a statement, returning a value from the block is not yet supported.
|
as a statement, returning a value from the block is not yet supported.
|
||||||
|
|
||||||
|
|||||||
@@ -250,23 +250,23 @@ fn report_errors(errors: Vec<Simple<String, Span>>, sources: &Sources) {
|
|||||||
|
|
||||||
type LexerError = Simple<char, Span>;
|
type LexerError = Simple<char, Span>;
|
||||||
fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = LexerError> {
|
fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = LexerError> {
|
||||||
let float64 = text::int(10)
|
let float64 = text::digits(10)
|
||||||
.chain::<char, _, _>(just('.').chain(text::digits(10)))
|
.chain::<char, _, _>(just('.').chain(text::digits(10)))
|
||||||
.then_ignore(just("f64"))
|
.then_ignore(just("f64"))
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.map(Token::Float64);
|
.map(Token::Float64);
|
||||||
|
|
||||||
let float = text::int(10)
|
let float = text::digits(10)
|
||||||
.chain::<char, _, _>(just('.').chain(text::digits(10)))
|
.chain::<char, _, _>(just('.').chain(text::digits(10)))
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.map(Token::Float);
|
.map(Token::Float);
|
||||||
|
|
||||||
let integer = just::<_, _, LexerError>("0x")
|
let integer = just::<_, _, LexerError>("0x")
|
||||||
.ignore_then(text::int(16))
|
.ignore_then(text::digits(16))
|
||||||
.try_map(|n, span| {
|
.try_map(|n, span| {
|
||||||
u64::from_str_radix(&n, 16).map_err(|err| LexerError::custom(span, err.to_string()))
|
u64::from_str_radix(&n, 16).map_err(|err| LexerError::custom(span, err.to_string()))
|
||||||
})
|
})
|
||||||
.or(text::int(10).try_map(|n: String, span: Span| {
|
.or(text::digits(10).try_map(|n: String, span: Span| {
|
||||||
n.parse::<u64>()
|
n.parse::<u64>()
|
||||||
.map_err(|err| LexerError::custom(span, err.to_string()))
|
.map_err(|err| LexerError::custom(span, err.to_string()))
|
||||||
}))
|
}))
|
||||||
|
|||||||
Reference in New Issue
Block a user