turbo-editors/turbo-moonbitpublic Fork 0
v1.0.3
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-moonbit.git
git clone ssh://git@rickub.com/turbo-editors/turbo-moonbit.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

tour.mbt · 255 lines · 7.4 KBMoonBit Blame HistoryRaw
📦 Turbo MoonBit cc1f595 k33g yesterday1// An ordinary line comment.
2
3///|
4/// A doc comment. `///|` above is the separator MoonBit's own formatter puts
5/// between top-level items — it is a comment too, and coloured as one.
6///
7/// Everything below compiles. `moon check` reports no warnings and no errors,
8/// which is the point: a colouring demo that does not build is a screenshot.
9
10// ── literals ────────────────────────────────────────────────────────────────
11
12///|
13fn literals() -> Unit {
14 // Strings, and the four other quoted forms.
15 let plain = "an ordinary string"
16 let escaped = "a quote \" and a backslash \\ and a newline \n"
17 let unicode = "\u{1F31C} é"
18 let bytes = b"\xDE\xAD\xBE\xEF"
19 let ch = 'x'
20 let escaped_char = '\n'
21 let byte_char = b'A'
22
23 // Interpolation is one string span, brace to brace: the expression inside is
24 // deliberately not coloured as code.
25 let name = "MoonBit"
26 let interpolated = "hello \{name}, and \{1 + 2}"
27
28 // The one line in this file the editor colours *wrongly*, kept on purpose.
29 // A string nested inside an interpolation ends the outer literal as far as
30 // the scanner is concerned, so `yes` and `no` below come out as identifiers
31 // rather than as part of the string. The compiler disagrees, and is right;
32 // finding the real end needs the parser. See reference/languages.md.
33 let nested = "answer: \{if true { "yes" } else { "no" }}"
34
35 // A multi-line string is a run of lines, each complete in itself. #| is
36 // literal; $| interpolates.
37 let raw =
38 #| {"note": "braces and \backslashes are literal here"}
39 #| second line
40 let woven =
41 $| the name again: \{name}
42 $| and arithmetic: \{6 * 7}
43
44 println(plain)
45 println(escaped)
46 println(unicode)
47 println("bytes: \{bytes.length()} of them")
48 println("chars: \{ch} \{escaped_char.to_int()} \{byte_char.to_int()}")
49 println(interpolated)
50 println(nested)
51 println(raw)
52 println(woven)
53}
54
55// ── numbers ─────────────────────────────────────────────────────────────────
56
57///|
58/// Every numeric form the grammar allows, including the suffixes — which are
59/// upper case or they are not suffixes at all.
60fn numbers() -> Unit {
61 let decimal = 1_000_000
62 let hexadecimal = 0xFF_FF
63 let octal = 0o17
64 let binary = 0b1010_1010
65 let double = 1.5
66 let trailing_point = 1.0
67 let exponent = 1.5e-3
68 let hex_float = 0x1.8p3
69 let unsigned : UInt = 42U
70 let long : Int64 = 42L
71 let unsigned_long : UInt64 = 42UL
72 let big : BigInt = 42N
73 let single : Float = 1.0F
74
75 // An integer ends before `..`, so this is 1, then ..=, then 5 — not the
76 // double `1.` followed by `.=5`.
77 let mut sum = 0
78 for i in 1..<=5 {
79 sum = sum + i
80 }
81 for i in 0..<3 {
82 sum = sum - i
83 }
84
85 println("\{decimal} \{hexadecimal} \{octal} \{binary}")
86 println("\{double} \{trailing_point} \{exponent} \{hex_float}")
87 println("\{unsigned} \{long} \{unsigned_long} \{big} \{single}")
88 println("range sum: \{sum}")
89}
90
91// ── types, traits, and the case rule ────────────────────────────────────────
92
93///|
94/// A capitalised name can only be a type, a trait or a constructor — that is a
95/// lexical rule in MoonBit, not a convention, so the scanner needs no table of
96/// built-in type names.
97pub(all) struct Point {
98 x : Int
99 y : Int
100} derive(Eq, Debug)
101
102///|
103pub(all) enum Shape {
104 Dot
105 Line(Point, Point)
106 Poly(Array[Point])
107} derive(Debug)
108
109///|
110pub(open) trait Describe {
111 fn describe(Self) -> String
112}
113
114///|
115pub impl Describe for Point with fn describe(self) {
116 "Point(\{self.x}, \{self.y})"
117}
118
119///|
120pub impl Show for Point with fn output(self, logger) {
121 logger.write_string(self.describe())
122}
123
124///|
125/// `extend` promotes a trait's method onto the type, so `p.describe()` works
126/// as well as `Describe::describe(p)`.
127extend Point with Describe::{describe}
128
129///|
130/// A labelled argument with a default: the call site may leave it out.
131fn walk(path : Array[Point], closed? : Bool = false) -> Int {
132 let steps = path.length()
133 if closed {
134 steps
135 } else {
136 steps - 1
137 }
138}
139
140// ── control flow ────────────────────────────────────────────────────────────
141
142///|
143/// Raised when a shape has no points to speak of.
144pub suberror Empty
145
146///|
147fn corners(shape : Shape) -> Int raise Empty {
148 match shape {
149 Dot => 1
150 Line(_, _) => 2
151 Poly(points) => {
152 guard points.length() > 0 else { raise Empty }
153 points.length()
154 }
155 }
156}
157
158///|
159fn control() -> Unit {
160 let square : Array[Point] = [
161 { x: 0, y: 0, },
162 { x: 1, y: 0, },
163 { x: 1, y: 1, },
164 { x: 0, y: 1, },
165 ]
166 println("open path steps: \{walk(square)}")
167 println("closed path steps: \{walk(square, closed=true)}")
168
169 for shape in [Dot, Line({ x: 0, y: 0, }, { x: 1, y: 1, }), Poly(square)] {
170 debug(shape)
171 println(" has \{corners(shape)} corner(s)") catch {
172 Empty => println(" has no corners")
173 }
174 }
175
176 // A `for` loop carrying accumulators, with `break` to return a value and
177 // `continue` to go round again. (The older `loop (a, b) { … }` form is
178 // deprecated; this is what replaced it.)
179 let counted = for i = 0, acc = 0 {
180 if i >= 10 {
181 break acc
182 } else if i % 2 == 0 {
183 continue i + 1, acc + i
184 } else {
185 continue i + 1, acc
186 }
187 }
188 println("even numbers below ten add to \{counted}")
189
190 // while, with a mutable binding.
191 let mut countdown = 3
192 while countdown > 0 {
193 countdown = countdown - 1
194 }
195 println("countdown reached \{countdown}")
196
197 // Option and Result, and the four constructors the language's readers know.
198 let found : Int? = Some(7)
199 let missing : Int? = None
200 let good : Result[Int, String] = Ok(1)
201 let bad : Result[Int, String] = Err("nope")
202 // Option and Result are printed with `debug`: interpolating them would go
203 // through Show, which the toolchain now steers away from for debugging.
204 debug(found)
205 debug(missing)
206 debug(good)
207 debug(bad)
208 println("truth values: \{true} \{false}")
209
210 // A tuple, and its accessor.
211 let pair = (1, "one")
212 println("pair.0 = \{pair.0}, pair.1 = \{pair.1}")
213
214 // The pipe operator.
215 let piped = [3, 1, 2] |> sorted
216 println("piped:")
217 debug(piped)
218}
219
220///|
221fn sorted(xs : Array[Int]) -> Array[Int] {
222 let copy = xs.copy()
223 copy.sort()
224 copy
225}
226
227// ── attributes ──────────────────────────────────────────────────────────────
228
229///|
230/// An attribute takes the whole line: after the dotted name, everything up to
231/// the newline is its raw payload.
232#deprecated("kept only so the colouring has something to show")
233pub fn old_name() -> Int {
234 1
235}
236
237///|
238/// A user-defined attribute has a namespace and is ignored by the compiler.
239#custom.note(kind="demo", enabled=true)
240fn annotated() -> Int {
241 2
242}
243
244// ── the entry point ─────────────────────────────────────────────────────────
245
246///|
247fn main {
248 literals()
249 println("")
250 numbers()
251 println("")
252 control()
253 println("")
254 println("annotated() = \{annotated()}")
255}