Syntax.icl 39.9 KB
Newer Older
Camil Staps's avatar
Camil Staps committed
1
implementation module Builtin.Syntax
Camil Staps's avatar
Camil Staps committed
2

Camil Staps's avatar
Camil Staps committed
3
import StdArray
4
import StdFunctions
Camil Staps's avatar
Camil Staps committed
5
import StdList
Camil Staps's avatar
Camil Staps committed
6
import StdString
Camil Staps's avatar
Camil Staps committed
7

Camil Staps's avatar
Camil Staps committed
8
import Data.Error
Camil Staps's avatar
Camil Staps committed
9 10 11 12
from Data.Func import $
import Data.Maybe
import Text

13 14
import Regex
exact s = regex ("^" +++ s +++ "$")
Camil Staps's avatar
Camil Staps committed
15

Camil Staps's avatar
Camil Staps committed
16 17
import Cloogle.API
import Cloogle.DB
Camil Staps's avatar
Camil Staps committed
18

Camil Staps's avatar
Camil Staps committed
19
import Builtin.Predef
Camil Staps's avatar
Camil Staps committed
20 21 22

builtin_syntax :: [SyntaxEntry]
builtin_syntax =
Mart Lubbers's avatar
Mart Lubbers committed
23 24
	[ bs_basicvalues
	, bs_case
Camil Staps's avatar
Camil Staps committed
25 26
	, bs_class
	, bs_code
Camil Staps's avatar
Camil Staps committed
27
	, bs_comments
28
	, bs_context
Camil Staps's avatar
Camil Staps committed
29 30 31 32
	, bs_define_constant
	, bs_define_graph
	, bs_dotdot
	, bs_exists
Camil Staps's avatar
Camil Staps committed
33
	, bs_extensible_adt
Camil Staps's avatar
Camil Staps committed
34
	, bs_forall
Mart Lubbers's avatar
Mart Lubbers committed
35
	, bs_foreign
36
	, bs_funcdep
Camil Staps's avatar
Camil Staps committed
37
	, bs_function_definition
Camil Staps's avatar
Camil Staps committed
38
	, bs_guard
Camil Staps's avatar
Camil Staps committed
39
	, bs_generic
Camil Staps's avatar
Camil Staps committed
40
	, bs_hierarchical_modules
Camil Staps's avatar
Camil Staps committed
41 42 43 44 45 46 47 48 49 50 51 52 53
	, bs_import
	, bs_infix
	, bs_instance
	, bs_lambda
	, bs_layout_rule
	, bs_let
	, bs_let_before
	, bs_list_expressions
	, bs_macro
	, bs_module
	, bs_newtype
	, bs_overloaded_type_variable
	, bs_pattern_named
54
	, bs_pattern_predicate
55 56
	, bs_qualified_identifier
	, bs_record_disambiguation
Camil Staps's avatar
Camil Staps committed
57 58 59 60 61 62 63
	, bs_selection_array
	, bs_selection_array_unique
	, bs_selection_record
	, bs_selection_record_unique
	, bs_strict
	, bs_synonym
	, bs_synonym_abstract
Camil Staps's avatar
Camil Staps committed
64 65
	, bs_type_definition
	, bs_type_specification
66
	, bs_unique
Camil Staps's avatar
Camil Staps committed
67 68 69 70 71 72 73 74 75
	, bs_update_array
	, bs_update_record
	, bs_where_class
	, bs_where_instance
	, bs_where_local
	, bs_with
	, bs_zf
	]

76
EX :: !String -> SyntaxExample 
77
EX c = {example=c, cleanjs_start=Nothing, bootstrap=[], requires_itask_compiler=False}
78
EXs :: !String !String -> SyntaxExample
79 80 81 82 83 84 85 86 87 88
EXs s c = {EX c & cleanjs_start=Just s}

add_imports :: ![String] !SyntaxExample -> SyntaxExample
add_imports is se = {se & bootstrap=["import " +++ mod \\ mod <- is] ++ se.bootstrap}

add_bootstrap :: !String !SyntaxExample -> SyntaxExample
add_bootstrap bs se = {se & bootstrap=se.bootstrap ++ [bs]}

requires_itask_compiler :: !SyntaxExample -> SyntaxExample
requires_itask_compiler se = {se & requires_itask_compiler=True}
Camil Staps's avatar
Camil Staps committed
89

Mart Lubbers's avatar
Mart Lubbers committed
90
bs_basicvalues =
91
	{ syntax_title         = "basic values"
Camil Staps's avatar
Camil Staps committed
92 93
	, syntax_patterns      = map exact ["'.'", "[+-]?\\d+", "[+-]?0[0-7]+", "[-+]?0x[0-9a-fA-F]+", "E"]
	, syntax_code          = ["0x...", "0...", "'...'", "...E..."]
Mart Lubbers's avatar
Mart Lubbers committed
94
	, syntax_description   =
Camil Staps's avatar
Camil Staps committed
95 96 97 98
		"Constant basic values can be of type {{`Int`}}, {{`Char`}} and {{`Real`}}. See also {{`Bool`}}.\n\n" +
		"Integers can be specified in decimal (default), octal (`0` prefix) or hexadecimal (`0x` prefix) notation.\n\n" +
		"Characters can either be printable characters (except `'`) or an escape sequence.\n" +
		"An escape sequence is a character escape, a hexademical escape (starting with `x`), an octal escape (starting with `0` to `7`) or a decimal escape (starting with `d`).\n\n" +
Mart Lubbers's avatar
Mart Lubbers committed
99 100
		"Reals can be suffixed by a power of ten in the scientific notation.\n\n" +
		"Basic values can also be pattern matched with these notations."
Camil Staps's avatar
Camil Staps committed
101 102 103 104 105 106
	, syntax_doc_locations = [CLR 6 "4.1.1" "_Toc311798017"]
	, syntax_examples      = map (EXs "rhs")
		[ "(42, -42, +42)          // Tuple with 42, -42 and 42 in decimal notation"
		, "(052, -052, +052)       // Tuple with 42, -42 and 42 in octal notation"
		, "(0x2a, -0x2a, +0x2A)    // Tuple with 42, -42 and 42 in hexadecimal notation"
		, "('a', '\\x2a', '\\052')   // Tuple with a normal character and twice the character with ASCII value 42"
107
		, "['\\n', '\\r', '\\f', '\\b', '\\t', '\\v', '\\\\', '\\'', '\\\"']\n" +
108
		  "                        // All character escapes"
Mart Lubbers's avatar
Mart Lubbers committed
109
		, "(42.0, -42.0, 42E-10, +42.0E+10, -42.0E10)\n" +
110
		  "                        // Several reals"
Mart Lubbers's avatar
Mart Lubbers committed
111 112 113
		]
	}

Camil Staps's avatar
Camil Staps committed
114 115
bs_case =
	{ syntax_title         = "case expression"
Camil Staps's avatar
Camil Staps committed
116
	, syntax_patterns      = map exact ["case", "of", "case of", "->", "="]
Camil Staps's avatar
Camil Staps committed
117
	, syntax_code          = ["case ... of ..."]
118 119 120 121
	, syntax_description   = join " "
		[ "Pattern match on an expression and do something depending on the alternative of the matching pattern."
		, "Both `->` and `=` can be used to separate patterns and alternatives, however, they cannot be mixed."
		]
Camil Staps's avatar
Camil Staps committed
122 123
	, syntax_doc_locations = [CLR 5 "3.4.2" "_Toc311798001"]
	, syntax_examples      =
124 125
		[ add_imports ["StdMaybe"] $ EXs "macro"
		  "isJust m = case m of\n\tJust _ -> True\n\t_      -> False"
Camil Staps's avatar
Camil Staps committed
126 127 128 129 130
		]
	}

bs_class =
	{ syntax_title         = "class"
Camil Staps's avatar
Camil Staps committed
131
	, syntax_patterns      = map exact ["class"]
Camil Staps's avatar
Camil Staps committed
132 133 134 135 136 137 138 139
	, syntax_code          =
		[ "class ... ... :: ..."
		, "class ... ... where ..."
		]
	, syntax_description   =
		"Classes are (sets of) overloaded functions. For classes with only one member function, a simplified syntax exists.\n\n" +
		"Types can instantiate classes with the {{`instance`}} keyword."
	, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
140
	, syntax_examples      = map EX
141
		[ "class zero a :: a // one member"
142
		, "class Text s      // multiple members\nwhere\n\ttextSize :: !s -> Int\n\tconcat :: ![s] -> s\n\t/* etc... */"
Camil Staps's avatar
Camil Staps committed
143 144 145 146 147
		]
	}

bs_code =
	{ syntax_title         = "ABC code"
Camil Staps's avatar
Camil Staps committed
148
	, syntax_patterns      = map exact ["code", "inline", "code inline"]
Camil Staps's avatar
Camil Staps committed
149 150 151 152 153
	, syntax_code          = ["... = code [inline] { ... }"]
	, syntax_description   =
		"A code block with raw ABC instructions, which can be used for primitive functions like integer addition, for linking with C, bypassing the type system... welcome down the rabbit hole!\n\n" +
		"When `inline` is used, the function will be inlined when applied in a strict context."
	, syntax_doc_locations = [CLR 13 "11.2" "_Toc311798115"]
154
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
155 156 157 158 159 160
		[ "add :: !Int !Int -> Int                   // Primitive function\nadd a b = code inline {\n\taddI\n}"
		, "sleep :: !Int !*World -> *(!Int, !*World) // Linking with C\nsleep n w = code {\n\tccall sleep \"I:I:A\"\n}"
		, "cast :: !.a -> .b                         // Bypassing the type system\ncast _ = code {\n\tno_op\n}"
		]
	}

Camil Staps's avatar
Camil Staps committed
161 162
bs_comments =
	{ syntax_title         = "comments"
163
	, syntax_patterns      = map exact ["//", "/\\*.*", "\\*/", "comments?"]
Camil Staps's avatar
Camil Staps committed
164 165 166
	, syntax_code          = ["// ...", "/* ... */"]
	, syntax_description   = "`//` adds a single-line comment. `/*` and `*/` encapsulate a multi-line comment. Multi-line comments can be nested."
	, syntax_doc_locations = [CLR 15 "B.2" "_Toc311798132"]
Camil Staps's avatar
Camil Staps committed
167 168 169 170
	, syntax_examples      = map EX
		[ "Start = 37 // Single-line comment"
		, "Start = /* inline or multi-line comment */ 37"
		]
Camil Staps's avatar
Camil Staps committed
171 172
	}

173
bs_context =
Camil Staps's avatar
Camil Staps committed
174
	{ syntax_title         = "type context"
175 176 177 178 179 180 181 182 183
	, syntax_patterns      = map exact ["\\|", "&", ",", "special"]
	, syntax_code          = [":: ... | ..., ... [special ...=...]", "| ... & ..., ..."]
	, syntax_description   = join "\n"
		[ "A type context indicates what {{class}}es must be instantiated by type variables.\n"
		, "For function types, the type context starts with `|`."
		, "Several classes can be given to the same variable with `,`."
		, "To add multiple restrictions, use `&`.\n"
		, "In constructors, the type context starts with `&`.\n"
		, "Uniqueness constraints can be given with `,`. For details, see under {{`,`}}.\n"
Camil Staps's avatar
Camil Staps committed
184 185 186
		, "With the `special` keyword, specialised instances for certain type instantiations are exported for efficiency.\n"
		, "The context of a generic function can only contain other generic functions."
		, "The generic context is written without kinds and separated by `,` as seen in the example."
187 188
		]
	, syntax_doc_locations = [CLR 8 "6.2" "_Toc311798057"]
189 190 191 192 193 194 195 196
	, syntax_examples      = map (add_imports ["StdEnv","Data.GenEq"] o EX)
		[ "add :: a a -> a | + a              // a must instantiate +\nadd x y = x + y"
		, "sum :: [a] -> a | zero, + a        // a must instantiate zero and +\nsum []     = zero\nsum [x:xs] = x + sum xs"
		, "(<+) infixr 5 :: a b -> String\n" +
		  "\t| toString a & toString b      // a and b must instantiate toString\n" +
		  "(<+) x y = toString x +++ toString y"
		, "contains :: a [a] -> Bool special a=Int // specialised instance for integer lists for efficiency"
		, "generic gFun a | gEq a :: a -> Int // generic context"
197 198 199
		]
	}

Camil Staps's avatar
Camil Staps committed
200 201
bs_define_constant =
	{ syntax_title         = "graph definition"
Camil Staps's avatar
Camil Staps committed
202
	, syntax_patterns      = map exact ["=:"]
Camil Staps's avatar
Camil Staps committed
203 204 205 206 207 208
	, syntax_code          = ["... =: ..."]
	, syntax_description   =
		"Defining constants with `=:` at the top level makes sure they are shared through out the program; hence, they are evaluated only once.\n\n" +
		"This is the default understanding of `=` in local scope.\n\n" +
		"The inverse is {{`=>`}}, which defines an identifier to be a constant function."
	, syntax_doc_locations = [CLR 5 "3.6" "_Toc311798007"]
209
	, syntax_examples      = [add_imports ["StdEnum"] $ EXs "macro" "mylist =: [1..10000]"]
Camil Staps's avatar
Camil Staps committed
210 211 212
	}
bs_define_graph =
	{ syntax_title         = "constant function definition"
Camil Staps's avatar
Camil Staps committed
213
	, syntax_patterns      = map exact ["=>"]
Camil Staps's avatar
Camil Staps committed
214 215
	, syntax_code          = ["... => ..."]
	, syntax_description   =
Camil Staps's avatar
Camil Staps committed
216
		"Defining constants with `=>` makes sure they are interpreted as constant functions; hence, they are evaluated every time they are needed.\n\n" +
Camil Staps's avatar
Camil Staps committed
217 218 219
		"This is the default understanding of `=` in global scope.\n\n" +
		"The inverse is {{`=:`}}, which defines an identifier to be a graph."
	, syntax_doc_locations = [CLR 5 "3.6" "_Toc311798007"]
220
	, syntax_examples      = [add_imports ["StdEnum"] $ EXs "macro" "mylist => [1..10000]"]
Camil Staps's avatar
Camil Staps committed
221 222 223 224
	}

bs_dotdot =
	{ syntax_title         = "dotdot expression"
Camil Staps's avatar
Camil Staps committed
225
	, syntax_patterns      = map exact ["\\[\\w\\.\\.\\]", "\\[\\w\\.\\.\\w\\]", "\\[\\w,\\w\\.\\.\\]", "\\[\\w,\\w\\.\\.\\w\\]", "dotdot", "dot-dot", "\\.\\."]
Camil Staps's avatar
Camil Staps committed
226 227 228 229 230
	, syntax_code          = ["[i..]", "[i..k]", "[i,j..]", "[i,j..k]"]
	, syntax_description   =
		"A shorthand for lists of enumerable types.\n\n" +
		"To use these expressions, you must import {{`StdEnum`}}. The underlying functions are defined in {{`_SystemEnum`}}."
	, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798023"]
231
	, syntax_examples      = map (add_imports ["StdEnum"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
232 233 234 235 236 237 238 239 240
		[ "xs = [0..]     // 0, 1, 2, 3, ..."
		, "xs = [0,2..]   // 0, 2, 4, 6, ..."
		, "xs = [0..10]   // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
		, "xs = [0,2..10] // 0, 2, 4, 6, 8, 10"
		]
	}

bs_exists =
	{ syntax_title         = "existential quantifier"
241
	, syntax_patterns      = map exact ["E", "E\\.*", "existential"]
Camil Staps's avatar
Camil Staps committed
242 243 244
	, syntax_code          = [":: ... = E. ...: ..."]
	, syntax_description   = "Existential quantifiers make it possible to define (recursive) objects of the same type with different types of content."
	, syntax_doc_locations = [CLR 7 "5.1.3" "_Toc311798042"]
245
	, syntax_examples      = [EX ":: List = E.e: Cons e List | Nil\nStart = Cons 5 (Cons 'a' (Cons \"abc\" Nil))"]
Camil Staps's avatar
Camil Staps committed
246 247
	}

Camil Staps's avatar
Camil Staps committed
248 249
bs_extensible_adt =
	{ syntax_title         = "extensible algebraic data type"
Camil Staps's avatar
Camil Staps committed
250
	, syntax_patterns      = map exact ["\\.\\.", "\\|"]
Camil Staps's avatar
Camil Staps committed
251 252 253 254 255
	, syntax_code          = [":: T | ...", ":: T = ... | ... | .."]
	, syntax_description   = join " "
		[ "Extensible algebraic data types are ADTs that can be extended in other modules."
		, "One module can declare the ADT as extendible by adding the `..` constructor."
		, "Other modules can then extend it."
Mart Lubbers's avatar
Mart Lubbers committed
256
		, "It is not possible to derive generic functions for EADTs."
Camil Staps's avatar
Camil Staps committed
257
		]
Mart Lubbers's avatar
Mart Lubbers committed
258
	, syntax_doc_locations = []
259 260 261 262 263 264 265
	, syntax_examples      =
		[ EX
		  ":: T = ..      // Declare T as an EADT"
		, EX
		  ":: T = C1 | .. // Declare T to be an EADT with at least the constructor C1"
		, add_bootstrap ":: T = .." $ EX
		  ":: T | C       // Extend the EADT T with constructor C"
Mart Lubbers's avatar
Mart Lubbers committed
266 267 268
		]
	}

Camil Staps's avatar
Camil Staps committed
269 270
bs_forall =
	{ syntax_title         = "universal quantifier"
Camil Staps's avatar
Camil Staps committed
271
	, syntax_patterns      = map exact ["A", "A\\.*"]
Camil Staps's avatar
Camil Staps committed
272 273 274
	, syntax_code          = ["A. ...:"]
	, syntax_description   = "Explicitly marks polymorphic type variables. Clean does not yet allow universal quantifiers on the topmost level."
	, syntax_doc_locations = [CLR 5 "3.7.4" "_Toc311798013"]
275 276
	, syntax_examples      = map (add_imports ["StdEnv"] o EX)
		[ "h :: (A.a: [a] -> Int) -> Int // The quantifier is needed to apply the function to both a [Int] and a [Char]\nh f = f [1..100] + f ['a'..'z']"
277
		, ":: T = C (A.a: a -> a)        // In a type"
278
		, "hd :: A.a: [a] -> a           // Not allowed: A. on the topmost level"
Camil Staps's avatar
Camil Staps committed
279 280 281
		]
	}

Mart Lubbers's avatar
Mart Lubbers committed
282 283
bs_foreign =
	{ syntax_title         = "foreign export"
Camil Staps's avatar
Camil Staps committed
284
	, syntax_patterns      = map exact ["foreign", "export", "ccall", "stdcall"]
Mart Lubbers's avatar
Mart Lubbers committed
285 286 287 288
	, syntax_code          =
		[ "foreign export [ccall | stdcall] ..."
		]
	, syntax_description   =
Camil Staps's avatar
Camil Staps committed
289
		"Exports the Clean function symbol to the binary.\n\n" +
Mart Lubbers's avatar
Mart Lubbers committed
290
		"This is only possible if the function is also in the definition module and all arguments are basic types or tuples and fully strict."
Mart Lubbers's avatar
Mart Lubbers committed
291
	, syntax_doc_locations = [CLR 13 "11.1" "_Toc311798114"]
292
	, syntax_examples      = map EX
Mart Lubbers's avatar
Mart Lubbers committed
293 294 295
		[ "foreign export factorial         // Export the factorial function"
		, "foreign export stdcall factorial // Idem but with the stdcall calling convention"
		]
Mart Lubbers's avatar
Mart Lubbers committed
296
	}
Mart Lubbers's avatar
Mart Lubbers committed
297

298 299
bs_funcdep =
	{ syntax_title         = "functional dependency"
Camil Staps's avatar
Camil Staps committed
300
	, syntax_patterns      = map exact ["~"]
301
	, syntax_code          =
Camil Staps's avatar
Camil Staps committed
302
		[ "class ... ~... ..."
303 304 305
		]
	, syntax_description   =
		"Lets you point the type checker to the type that determines the other types.\n\n" +
Camil Staps's avatar
Camil Staps committed
306
		"Most often this is the return type (undocumented and experimental)."
307
	, syntax_doc_locations = []
308 309
	, syntax_examples      = map (requires_itask_compiler o EX)
		[ "class plus a b ~c :: a b -> c\n" +
Camil Staps's avatar
Camil Staps committed
310
		  "instance plus Int Int Int where plus x y = x + y\n" +
311
		  "Start = plus 1 (plus 1 1) // Overloading can be resolved because we told the compiler that c determines the other types."
312 313 314
		]
	}

Camil Staps's avatar
Camil Staps committed
315 316 317 318
bs_function_definition =
	{ syntax_title         = "function definition"
	, syntax_patterns      = map exact ["="]
	, syntax_code          = ["... = ..."]
Camil Staps's avatar
Camil Staps committed
319 320 321 322 323
	, syntax_description   = join "\n"
		[ "Specifies the implementation of a function\n."
		, "Instead of `=`, also {{`=:`}} and {{`=>`}} may be used to separate the pattern from the right-hand side."
		, "These have different semantics."
		]
Camil Staps's avatar
Camil Staps committed
324 325 326 327 328 329
	, syntax_doc_locations = [CLR 5 "3" "_Toc311797995"]
	, syntax_examples      = map EX
		[ "map :: (a -> b) [a] -> [b]\nmap f []     = []\nmap f [x:xs] = [f x:map f xs]"
		]
	}

Camil Staps's avatar
Camil Staps committed
330 331 332 333 334 335 336 337 338 339 340 341 342
bs_guard =
	{ syntax_title         = "guard"
	, syntax_patterns      = map exact ["\\|", "=", "otherwise"]
	, syntax_code          = ["| ... = ...", "| otherwise = ..."]
	, syntax_description   = join "\n"
		[ "Guards let you specify function alternatives with boolean expressions."
		, "A final `otherwise` guard can be used to ensure the function is total.\n"
		, "Guards can be nested with indentation."
		, "However, only the toplevel guards may be partial.\n"
		, "To separate the guard from the alternative, both {{`=`}} and {{`=>`}} may be used (with different semantics; see {{`=>`}})."
		, "However, one must be consistent with this throughout the function."
		]
	, syntax_doc_locations = [CLR 5 "3.3" "_Toc311797998"]
343
	, syntax_examples      = map (add_imports ["StdEnv"] o EX)
Camil Staps's avatar
Camil Staps committed
344 345 346 347
		[ "sign :: !Int -> Int\nsign n\n| n  < 0    = -1 // Negative number\n| n == 0    =  0 // Zero\n| otherwise =  1 // Must be positive"
		]
	}

Camil Staps's avatar
Camil Staps committed
348 349
bs_generic =
	{ syntax_title         = "generic function definition"
350
	, syntax_patterns      = map exact ["generic", "derive", "of", "with", "\\{\\|.*\\|\\}", "\\*!"]
Mart Lubbers's avatar
Mart Lubbers committed
351
	, syntax_code          = ["generic ... ... [| ...] [*!] :: ... ", "derive ... ... [of ...] [with ...]"]
352 353 354 355 356
	, syntax_description   = join " "
		[ "With generics, a function can be defined once and derived for (almost) all possible types."
		, "This avoids very similar code snippets."
		, "Generic functions are said to be kind-indexed, i.e., a generic is actually a group of functions with different types depending on the kind of the deriving type."
		]
Camil Staps's avatar
Camil Staps committed
357
	, syntax_doc_locations = [CLR 9 "7.2" "_Toc311798069"]
358 359 360 361
	, syntax_examples      =
		[ add_imports ["StdEnv","StdGeneric"] $ EX $
		  "generic gEq a :: !a !a -> Bool            // The type of a generic function\n" +
		  "gEq{|Int|} x y = x == y                   // Implementation of a generic\n" +
362
		  "gEq{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = fx x1 x2 && fy y1 y2"
363 364 365 366 367 368 369 370 371 372 373 374
		, add_imports ["StdMaybe", "Data.GenEq"] $ EX
		  "derive gEq Maybe                          // Deriving the gEq generic for type Maybe"
		, add_imports ["StdGeneric"] $ add_bootstrap "generic gConsName a :: a -> String" $ EX
		  "gConsName{|CONS of d|} _ _ = d.gcd_name   // Using type information"
		, add_imports ["StdGeneric"] $ add_bootstrap "generic gConsName a :: a -> String" $ EX
		  "gConsName{|CONS of {gcd_name}|} _ _ = gcd_name // Using a specific field of type information, the compiler can optimise the function"
		, add_imports ["StdGeneric", "StdMisc", "Data.GenDefault"] $ EX $
		  "generic gFun a | gDefault a :: a -> Int   // A generic function with a generic context. The context will become an argument.\n" +
		  "derive gFun CONS of {gcd_arity} with f _  // A derivation that does not use all arguments. The compiler can optimize even more.\n" +
		  "gFun{|CONS of {gcd_arity}|} f _ _ = undef // A derivation that does not use the context and only one field of the generic type descriptor, the compiler can optimize for this."
		, requires_itask_compiler $ EX $
		  "generic gShared a *! :: a                 // A generic function using a bimap without uniqueness attributes (only supported by the iTask compiler; see https://gitlab.science.ru.nl/clean-and-itasks/clean-language-report/blob/master/experimental/binumap.md)\n"
Camil Staps's avatar
Camil Staps committed
375 376 377
		]
	}

Camil Staps's avatar
Camil Staps committed
378 379 380 381 382 383 384 385 386
bs_hierarchical_modules =
	{ syntax_title         = "hierarchical module names"
	, syntax_patterns      = [exact "\\."]
	, syntax_code          = ["... . ..."]
	, syntax_description   = "Modules can be structured hierarchically. For instance, module `Control.Monad` can be found in `Control/Monad.[di]cl`."
	, syntax_doc_locations = []
	, syntax_examples      = [EX "definition module Control.Monad"]
	}

Camil Staps's avatar
Camil Staps committed
387 388
bs_import =
	{ syntax_title         = "imports"
Camil Staps's avatar
Camil Staps committed
389
	, syntax_patterns      = map exact ["import", "from", "qualified", "as", "=>", "code", "library"]
Camil Staps's avatar
Camil Staps committed
390 391 392 393 394 395 396 397 398 399 400 401
	, syntax_code          =
		[ "import [qualified] ... [as ...]"
		, "from ... import ..."
		, "import ... => qualified ..."
		, "import code from [library] ..."
		]
	, syntax_description   =
		"Imports code from other modules.\n\n" +
		"With the `from` keyword, one can achieve more granularity.\n\n" +
		"In case of name clashes, `qualified` can be used (undocumented).\n\n" +
		"Moreover, you can import from object files or windows DLLs."
	, syntax_doc_locations = [CLR 4 "2.5" "_Toc311797991"]
402
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
403 404 405 406 407 408
		[ "import StdEnv                          // Import all code from the StdEnv definition module"
		, "from StdFunc import o                  // Import only the o function from StdFunc"
		, "import qualified Data.Map              // Import Data.Map such that functions are available as e.g. 'Data.Map'.get."
		, "import code from \"tty.\"                // Import functions from the object file matching 'Clean System Files/tty.*'"
		, "import code from library \"msvcrt\"      // Import functions from linked DLLs according to the msvcrt file in Clean System Files.\n" +
		  "                                       // The file should start with the DLL name (e.g. msvcrt) and followed by one line per function you want to link."
409 410 411
		] ++ map (requires_itask_compiler o EX)
		[ "import qualified Data.Map as M         // Import Data.Map to use as e.g. 'M'.get (only supported by the iTask compiler)"
		, "import Control.Monad => qualified join // Import Control.Monad except for join; join is imported qualified (only supported by the iTask compiler)"
Camil Staps's avatar
Camil Staps committed
412 413 414 415 416
		]
	}

bs_infix =
	{ syntax_title         = "infix operator"
Camil Staps's avatar
Camil Staps committed
417
	, syntax_patterns      = map exact ["infix", "infixl", "infixr"]
Camil Staps's avatar
Camil Staps committed
418 419 420 421 422 423 424
	, syntax_code          = ["infix[l,r] [...]"]
	, syntax_description   =
		"Defines a function with arity 2 that can be used in infix position.\n\n" +
		"The following number, if any, determines the precedence.\n\n" +
		"`infixl` and `infixr` indicate associativity."
	, syntax_doc_locations = [CLR 5 "3.7.2" "_Toc311798011"]
	, syntax_examples      =
425 426 427
		[ EX          "(bitor) infixl 6 :: !Int !Int -> Int // Left-associative infix function with precedence 6"
		, EXs "macro" "(o) infixr 9                         // Infix macro\n(o) f g :== \\x -> f (g x)"
		, EX          ":: MyType = (:+:) infixl 6 Int Int   // Infix data constructor, can be used as (5 :+: 10)"
Camil Staps's avatar
Camil Staps committed
428 429 430 431 432
		]
	}

bs_instance =
	{ syntax_title         = "instance"
Camil Staps's avatar
Camil Staps committed
433
	, syntax_patterns      = map exact ["instance"]
Camil Staps's avatar
Camil Staps committed
434 435 436
	, syntax_code          = ["instance ... ... where ..."]
	, syntax_description   = "Defines an instantiation of a {{class}} for a type."
	, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
437
	, syntax_examples      = map (add_imports ["StdOverloaded"] o EX)
Camil Staps's avatar
Camil Staps committed
438 439 440 441 442 443 444
		[ "instance zero Int\nwhere\n\tzero = 0"
		, "instance zero Real\nwhere\n\tzero = 0.0"
		]
	}

bs_lambda =
	{ syntax_title         = "lambda abstraction"
Camil Staps's avatar
Camil Staps committed
445
	, syntax_patterns      = map exact ["lambda", "=", "->", "\\."]
Camil Staps's avatar
Camil Staps committed
446 447 448
	, syntax_code          = ["\\... -> ...", "\\... . ...", "\\... = ..."]
	, syntax_description   = "An anonymous, inline function."
	, syntax_doc_locations = [CLR 5 "3.4.1" "_Toc311798000"]
449
	, syntax_examples      = map (add_imports ["StdList"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
450 451 452 453 454 455 456 457
		[ "(o) f g = \\x -> f (g x)         // Simple lambda expression"
		, "swapall = map (\\(x,y) -> (y,x)) // Pattern matching in lambda arguments"
		, "mul     = \\x y -> x * y         // Multiple arguments (of course, it would be better to write `mul x y = x * y` or `mul = (*)`)"
		]
	}

bs_layout_rule =
	{ syntax_title         = "layout rule"
Camil Staps's avatar
Camil Staps committed
458
	, syntax_patterns      = map exact [";", "\\{", "\\}"]
Camil Staps's avatar
Camil Staps committed
459 460 461 462 463 464
	, syntax_code          = ["...;", "{ ... }"]
	, syntax_description   =
		"Most Clean programs are written using the layout rule, which means that scopes are indicated with indent levels." +
		"The layout sensitive mode can be turned off by adding a semicolon `;` at the end of the {{module}} line." +
		"Then, scopes have to be indicated with `{ ... }` and definitions have to end with `;`."
	, syntax_doc_locations = [CLR 4 "2.3.3" "_Toc311797989"]
465
	, syntax_examples      = [EX $
Camil Staps's avatar
Camil Staps committed
466 467 468 469 470 471 472 473 474 475 476 477 478
		"module test;\n" +
		"import StdEnv;\n" +
		"Start :: [(Int,Int)];\n" +
		"Start = [(x,y) \\\\ x <- odds, y <- evens];\n" +
		"where\n" +
		"{\n" +
		"\todds  = [1,3..9];\n" +
		"\tevens = [0,2..8];\n" +
		"}"]
	}

bs_let =
	{ syntax_title         = "let expression"
Camil Staps's avatar
Camil Staps committed
479
	, syntax_patterns      = map exact ["let", "in", "let in"]
Camil Staps's avatar
Camil Staps committed
480
	, syntax_code          = ["let ... in ..."]
Camil Staps's avatar
Camil Staps committed
481 482 483
	, syntax_description   = "An expression that introduces new scope."
	, syntax_doc_locations = [CLR 5 "3.5.1" "_Toc311798003"]
	, syntax_examples      =
484 485 486 487 488 489 490 491 492
		[ add_imports ["StdEnv"] $
		  EXs "macro"
		  "fac n = let fs = [1:1:[(fs!!(i-1)) + (fs!!(i-2)) \\\\ i <- [2..]]] in fs !! n"
		, add_imports ["StdMisc"] $
		  add_bootstrap "body = undef" $
		  add_bootstrap "expr = undef" $
		  add_bootstrap "expression = undef" $
		  EXs "macrorhs"
		  "let // Multi-line let expressions\n\tfunction args = body\n\tselector = expr\n\t// ...\nin expression"
Camil Staps's avatar
Camil Staps committed
493 494 495 496
		]
	}
bs_let_before =
	{ syntax_title         = "let before"
Camil Staps's avatar
Camil Staps committed
497
	, syntax_patterns      = map exact ["#", "#!"]
Camil Staps's avatar
Camil Staps committed
498 499 500 501
	, syntax_code          = ["#  ... = ...", "#! ... = ..."]
	, syntax_description   = "A {{`let`}} expression that can be defined before a guard or function body, which eases the syntax of sequential actions."
	, syntax_doc_locations = [CLR 5 "3.5.4" "_Toc311798006"]
	, syntax_examples      =
502 503 504 505 506 507 508
		[ add_imports ["StdEnv"] $ EX $
		  "readchars :: *File -> *([Char], *File)\n" +
		  "readchars f\n" +
		  "# (ok,c,f) = freadc f\n" +
		  "| not ok   = ([], f)\n" +
		  "# (cs,f)   = readchars f\n" +
		  "= ([c:cs], f)"
Camil Staps's avatar
Camil Staps committed
509 510 511 512 513
		]
	}

bs_list_expressions =
	{ syntax_title         = "list expression"
Camil Staps's avatar
Camil Staps committed
514
	, syntax_patterns      = map exact ["list", "\\[\\]", "\\[:\\]", ":", "\\[\\w:\\w\\]", "\\['.*"]
Camil Staps's avatar
Camil Staps committed
515 516 517 518 519 520
	, syntax_code          = ["[]", "[...:...]", "[..., ..., ...]", "['...']"]
	, syntax_description   =
		"A list can be composed of individual elements or a head and a tail. Special syntax is available for creating `[{{Char}}]` lists.\n\n" +
		"See also {{dotdot}} expressions.\n\n" +
		"The colon is not an operator in Clean, because it must always be surrounded by `[` and `]`. It can therefore not be curried, flipped, etc."
	, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798021"]
521
	, syntax_examples      = map (EXs "macro")
Camil Staps's avatar
Camil Staps committed
522
		[ "abc = ['a', 'b', 'c']     // Individual elements"
523 524 525
		, "abc = ['a':['b':['c':[]]]] // Head and tail, ending with the empty list"
		, "abc = ['abc']             // Syntax shorthand for [Char] lists"
		, "abc ['abc':rest] = True   // The shorthand can als be used to patternmatch"
Camil Staps's avatar
Camil Staps committed
526 527 528 529 530
		]
	}

bs_macro =
	{ syntax_title         = "macro"
Camil Staps's avatar
Camil Staps committed
531
	, syntax_patterns      = map exact [":==", "macro"]
Camil Staps's avatar
Camil Staps committed
532 533 534 535 536
	, syntax_code          = ["... :== ..."]
	, syntax_description   =
		"A macro is a compile-time rewrite rule. It can be used for constants, inline subtitutions, renaming functions, conditional compilation, etc.\n\n" +
		"Macros can appear in patterns to match on constants."
	, syntax_doc_locations = [CLR 12 "10.3" "_Toc311798111"]
537
	, syntax_examples      = map (EXs "macro")
Camil Staps's avatar
Camil Staps committed
538 539 540 541 542 543 544 545
		[ "flip f a b :== f b a                    // Useful for currying"
		, "IF_INT_64_OR_32 int64 int32 :== int64   // Conditional compilation"
		, "(o) infixr 9                            // Function composition. Doing this at run-time would be slow\n(o) f g :== \\x -> f (g x)"
		]
	}

bs_module =
	{ syntax_title         = "module heading"
Camil Staps's avatar
Camil Staps committed
546
	, syntax_patterns      = map exact ["module", "definition", "implementation", "system", "definition module", "implementation module", "system module"]
Camil Staps's avatar
Camil Staps committed
547 548 549
	, syntax_code          = ["[definition,implementation,system] module ..."]
	, syntax_description   = "The heading of a Clean file. Definition modules describe what things are exported (dcl files), implementation modules how they are implemented (icl files)."
	, syntax_doc_locations = [CLR 4 "2.2" "_Toc311797983"]
550
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
551
		[ "definition module StdList     // Exported definitions of list functions"
Camil Staps's avatar
Camil Staps committed
552 553 554 555 556 557 558
		, "implementation module StdList // The implementations of the functions"
		, "module test                   // An implementation module without corresponding dcl"
		, "system module StdInt          // The definitions of a module that contains foreign code (see section 2.6 of the language report)"
		]
	}

bs_newtype =
559
	{ syntax_title         = "newtype definition"
Camil Staps's avatar
Camil Staps committed
560
	, syntax_patterns      = map exact ["=:", "newtype"]
Camil Staps's avatar
Camil Staps committed
561 562 563 564 565
	, syntax_code          = [":: ... =: ... ..."]
	, syntax_description   = "A newtype is a type synonym at run-time but treated as a real type at compile-time.\n"
	                       + "This allows the creation of separate instances without overhead."
	, syntax_doc_locations = []
	, syntax_examples      =
566 567
		[ EX ":: T =: T Int"
		, EX ":: T a =: T a"
Camil Staps's avatar
Camil Staps committed
568 569 570 571
		]
	}

bs_overloaded_type_variable =
572
	{ syntax_title         = "overloaded type variable"
Camil Staps's avatar
Camil Staps committed
573
	, syntax_patterns      = map exact ["\\^", "\\w\\^"]
Camil Staps's avatar
Camil Staps committed
574 575 576
	, syntax_code          = ["... :: ...^"]
	, syntax_description   = "A pattern match on the type of a dynamic depending on the type of the function."
	, syntax_doc_locations = [CLR 10 "8.2.5" "_Toc311798087"]
577 578 579 580 581 582 583
	, syntax_examples      =
		[ add_imports ["StdMaybe"] $
		  EX $
		  "unpack :: Dynamic -> Maybe a | TC a\n" +
		  "unpack (x :: a^) = Just x // Only values of type a\n" +
		  "unpack _         = Nothing"
		]
Camil Staps's avatar
Camil Staps committed
584 585 586
	}

bs_pattern_named =
587
	{ syntax_title         = "pattern match"
Camil Staps's avatar
Camil Staps committed
588
	, syntax_patterns      = map exact ["=:"]
Camil Staps's avatar
Camil Staps committed
589 590 591
	, syntax_code          = ["...=:(...)"]
	, syntax_description   = "Give a name to the expression of a pattern to be able to use the whole expression without creating new graphs."
	, syntax_doc_locations = [CLR 5 "3.2" "_Toc311797997"]
592
	, syntax_examples      = map (add_imports ["StdMaybe"] o EX)
593 594
		[ "isJustU e=:(Just _) = (True, e) // On an ADT"
		, ":: Position = {px :: Int, py :: Int}\ngetx p=:{px} = (px, p) // On a record; this has type :: Position -> (Int, Position)"
Camil Staps's avatar
Camil Staps committed
595 596 597
		]
	}

598 599
bs_pattern_predicate =
	{ syntax_title         = "pattern predicate"
Camil Staps's avatar
Camil Staps committed
600
	, syntax_patterns      = map exact ["=:"]
601 602 603 604 605 606 607 608 609 610 611 612
	, syntax_code          = ["...=:(...)"]
	, syntax_description   = join " "
		[ "Check whether an expression matches a certain pattern (undocumented)."
		, "The result has type `Bool`."
		, "It is not possible to introduce new identifiers this way."
		, "For instance, one cannot use `if (mbx=:(Just x)) x 0`."
		, "Also, `=:` can not be used in prefix form because it is not an actual operator but a builtin."
		]
	, syntax_doc_locations = []
	, syntax_examples      = [EX "isSingleton l = l =: [_] // Match a value with a pattern"]
	}

613 614 615 616 617 618
bs_qualified_identifier =
	{ syntax_title         = "qualified identifier"
	, syntax_patterns      = map regex ["^'.+'", "^qualified$"]
	, syntax_code          = ["'...'. ..."]
	, syntax_description   = "The identifiers of {{`qualified`}} imports must be prepended with `'...'.`, where `...` is the name of the qualified import."
	, syntax_doc_locations = []
619 620 621 622 623
	, syntax_examples      =
		[ add_imports ["StdEnum"] $ EX
		  "import qualified StdList\nStart = 'StdList'.sum [0..10]"
		, add_imports ["StdEnum"] $ requires_itask_compiler $ EX
		  "import qualified StdList as L // requires the iTask compiler\nStart = 'L'.sum [0..10]"
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
		]
	}

bs_record_disambiguation =
	{ syntax_title         = "record disambiguation"
	, syntax_patterns      = map exact ["\\|"]
	, syntax_code          = ["{ ... | ... }"]
	, syntax_description   = join "\n"
		[ "Explicitly indicates the type of a record when it cannot be derived from the field names."
		]
	, syntax_doc_locations = []
	, syntax_examples      = map EX
		[ ":: R1 = {x :: Int, y :: Int}\n:: R2 = {x :: Int, y :: Int}\nStart = {R1 | x=37, y=42}"
		]
	}

Camil Staps's avatar
Camil Staps committed
640 641
bs_selection_array =
	{ syntax_title         = "array selection"
Camil Staps's avatar
Camil Staps committed
642
	, syntax_patterns      = map exact ["\\.\\[\\]", "\\.\\[.*\\]", "\\.\\[,.*\\]", "\\.\\[.*,.*\\]"]
Camil Staps's avatar
Camil Staps committed
643 644 645
	, syntax_code          = [".[i]", ".[i,j,...]"]
	, syntax_description   = "Select an element from a (possibly multidimensional) array. The indexes must have the type {{`Int`}}."
	, syntax_doc_locations = [CLR 6 "4.4.1" "_Toc311798033"]
646 647 648
	, syntax_examples      = map (add_imports ["StdEnv"] o EXs "macro")
		[ "five = {!1,2,3,4,5,6,7,8,9,10}.[4]     // Arrays are zero-indexed"
		, "five = {!{!1,2},{3,4,5},{6,7,8}}.[1,2] // This is equivalent to (...).[1].[2]"
Camil Staps's avatar
Camil Staps committed
649 650 651 652
		]
	}
bs_selection_array_unique =
	{ syntax_title         = "unique array selection"
Camil Staps's avatar
Camil Staps committed
653
	, syntax_patterns      = map exact ["!\\[\\]", "!\\[.*\\]", "!\\[,.*\\]", "!\\[.*,.*\\]"]
Camil Staps's avatar
Camil Staps committed
654 655 656
	, syntax_code          = ["![i]", "![i,j,...]"]
	, syntax_description   = "Select an element from a (possibly multidimensional, possibly unique) array and return both the element and the array. The indexes must have the type {{`Int`}}."
	, syntax_doc_locations = [CLR 6 "4.4.1" "_Toc311798033"]
657 658 659
	, syntax_examples      = map (add_imports ["StdEnv"] o EXs "macro")
		[ "(five,arr) = {!1,2,3,4,5,6,7,8,9,10}![4]"
		, "(five,arr) = {!{!1,2},{3,4,5},{6,7,8}}![1,2]"
Camil Staps's avatar
Camil Staps committed
660 661 662 663
		]
	}
bs_selection_record =
	{ syntax_title         = "record selection"
Camil Staps's avatar
Camil Staps committed
664
	, syntax_patterns      = map exact ["\\."]
Camil Staps's avatar
Camil Staps committed
665 666 667
	, syntax_code          = ["."]
	, syntax_description   = "Select a field from a (possibly multilevel) record."
	, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798050"]
668 669 670 671 672
	, syntax_examples      = map
		( add_bootstrap ":: Position = {px :: Int, py :: Int}"
		o add_bootstrap ":: Position3D = {pxy :: Position, pz :: Int}"
		o EXs "macro"
		)
Camil Staps's avatar
Camil Staps committed
673 674 675 676 677 678 679
		[ "five = {px=5, py=10}.px"
		, "five = {pxy={px=5, py=10}, pz=2}.pxy.px"
		, "five = {px=5, py=10}.Position.px // If multiple records have a field px, the type name can be used for disambiguation"
		]
	}
bs_selection_record_unique =
	{ syntax_title         = "unique record selection"
Camil Staps's avatar
Camil Staps committed
680
	, syntax_patterns      = map exact ["!"]
Camil Staps's avatar
Camil Staps committed
681 682 683
	, syntax_code          = ["!"]
	, syntax_description   = "Select a field from a (possibly multilevel, possibly unique) record and return both the field data and the record."
	, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798050"]
684 685 686 687 688
	, syntax_examples      = map
		( add_bootstrap ":: Position = {px :: Int, py :: Int}"
		o add_bootstrap ":: Position3D = {pxy :: Position, pz :: Int}"
		o EXs "macro"
		)
Camil Staps's avatar
Camil Staps committed
689 690 691 692 693 694 695 696 697
		[ "(five,rec) = {px=5, py=10}!px"
		, "(five,rec) = {pxy={px=5, py=10}, pz=2}!pxy.px // Only the first field should have the exclamation mark"
		, "(five,rec) = {px=5, py=10}!Position.px // If multiple records have a field px, the type name can be used for disambiguation\n" +
		  "                                       // The language report is erroneous here. It is !Position.px, not .Position!px."
		]
	}

bs_strict =
	{ syntax_title         = "strictness annotation"
Camil Staps's avatar
Camil Staps committed
698
	, syntax_patterns      = map exact ["strict", "!"]
Camil Staps's avatar
Camil Staps committed
699 700 701
	, syntax_code          = ["!"]
	, syntax_description   = "Override the lazy evaluation strategy: the argument must be evaluated to head normal form before the function is entered."
	, syntax_doc_locations = [CLR 5 "3.7.5" "_Toc311798014", CLR 12 "10" "_Toc311798103"]
702
	, syntax_examples      = [EX "acker :: !Int !Int -> Int"]
Camil Staps's avatar
Camil Staps committed
703 704 705 706
	}

bs_synonym =
	{ syntax_title         = "synonym type definition"
Camil Staps's avatar
Camil Staps committed
707
	, syntax_patterns      = map exact ["synonym", ":=="]
Camil Staps's avatar
Camil Staps committed
708 709 710
	, syntax_code          = [":: ... :== ..."]
	, syntax_description   = "Defines a new type name for an existing type."
	, syntax_doc_locations = [CLR 7 "5.3" "_Toc311798052"]
711
	, syntax_examples      = [EX ":: String :== {#Char}"]
Camil Staps's avatar
Camil Staps committed
712 713 714
	}
bs_synonym_abstract =
	{ syntax_title         = "abstract synonym type definition"
Camil Staps's avatar
Camil Staps committed
715
	, syntax_patterns      = map exact ["synonym", ":=="]
Camil Staps's avatar
Camil Staps committed
716 717 718
	, syntax_code          = [":: ... (:== ...)"]
	, syntax_description   = "Defines a new type name for an existing type, while the type behaves as an abstract type for the programmer. This allows compiler optimisations on abstract types."
	, syntax_doc_locations = [CLR 7 "5.4.1" "_Toc311798054"]
719
	, syntax_examples      = [EX ":: Stack a (:== [a])"]
Camil Staps's avatar
Camil Staps committed
720 721
	}

Camil Staps's avatar
Camil Staps committed
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
bs_type_definition =
	{ syntax_title         = "type definition"
	, syntax_patterns      = map exact ["::", "=", "\\|"]
	, syntax_code          = [":: ..."]
	, syntax_description   = "Defines a new type. There are too many possibilities to list hear; see the documentation."
	, syntax_doc_locations = [CLR 7 "5" "_Toc311798038"]
	, syntax_examples      = map EX
		[ join "\n\t" [":: Day // An algebraic data type","= Mon","| Tue","| Wed","| Thu","| Fri","| Sat","| Sun"]
		, ":: Position = // A record type\n\t{ x :: Int\n\t, y :: Int\n\t}"
		]
	}

bs_type_specification =
	{ syntax_title         = "type specification"
	, syntax_patterns      = map exact ["::"]
	, syntax_code          = ["... :: ..."]
	, syntax_description   = "Specifies the type of a function."
	, syntax_doc_locations = [CLR 5 "3.7" "_Toc311798009"]
	, syntax_examples      = map EX
		[ "map :: (a -> b) [a] -> [b] // map has arity 2\nmap f []     = []\nmap f [x:xs] = [f x:map f xs]"
		, "map :: (a -> b) -> [a] -> [b] // map has arity 1\nmap f = \\xs -> case xs of\n\t[]    -> []\n\t[x:xs] -> [f x:map f xs]"
		]
	}

746 747
bs_unique =
	{ syntax_title         = "uniqueness annotation"
Camil Staps's avatar
Camil Staps committed
748
	, syntax_patterns      = map exact ["\\*", "\\.", "\\w:", "\\[.*<=.*\\]", ",", "<="]
749
	, syntax_code          =
Camil Staps's avatar
Camil Staps committed
750 751
		[ "*..."
		, ". ..."
Camil Staps's avatar
Camil Staps committed
752
		, "...:..., [...<=...], [...<=...], ..."
Camil Staps's avatar
Camil Staps committed
753 754 755
		]
	, syntax_description   = join " "
		[ "Annotates a type with its uniqueness."
Camil Staps's avatar
Camil Staps committed
756 757 758 759 760 761 762
		, "A type can either be unique (`*`), not unique (not annotated), possibly unique (`.`) or relatively unique (identifier and `, [...<=...]` after the type context)."
		, "Because uniqueness is binary, there is only one case where `[u<=v]` is not satisfied; when `u` is unique but `v` is not."
		, "\n\nOn function types, *uniqueness propagation* is implicit (see section 9.2 of the language report)."
		, "However, when using unique types in a function or an ADT this has to be made explicit; for instance:"
		, "`T = T (Int, *File)` has to be `T = T *(Int, *File)`."
		, "Functions have to be split up into arity 1 and the subfunctions must be annotated as well; for instance:"
		, "`T = T (Int *Int -> *Int)` has to be `T = T (Int -> *(*Int -> *Int))`."
Mart Lubbers's avatar
Mart Lubbers committed
763
		]
764
	, syntax_doc_locations = [CLR 11 "9.1" "_Toc311798093"]
765
	, syntax_examples      = map (add_imports ["StdEnv"] o EX)
766 767 768 769
		[ "Start :: *World -> *World   // World is unique"
		, "copyArray :: *(a e) -> *(*a e, *a e) | Array a e // Add parentheses when needed"
		, "f :: .a -> .a               // f works on unique and non-unique values"
		, "f :: v:a u:b -> u:b, [v<=u] // f works when a is less unique than b"
770 771 772
		]
	}

Camil Staps's avatar
Camil Staps committed
773 774
bs_update_array =
	{ syntax_title         = "array update"
Camil Staps's avatar
Camil Staps committed
775
	, syntax_patterns      = map exact ["&", "\\{.*&.*\\[.*].*=.*\\}"]
Camil Staps's avatar
Camil Staps committed
776
	, syntax_code          =
777 778 779
		[ "{ a & [i]=x, [j]=y, ... }        // Updates a by setting index i to x, j to y, ..."
		, "# a & [i]=x, [j]=y, ...          // Same as # a = {a & [i]=x, [j]=y, ...}" // See https://clean.cs.ru.nl/Clean_2.3
		, "{ a & [i]=i \\\\ i <- [0,2..9] } // Fancy things can be done if you combine this with a ZF-expression. E.g. give the first 5 even indices the value of their index"
Camil Staps's avatar
Camil Staps committed
780 781 782 783 784 785 786
		]
	, syntax_description   = "Updates an array by creating a copy and replacing one or more elements."
	, syntax_doc_locations = [CLR 6 "4.4.1" "_Toc311798032"]
	, syntax_examples      = []
	}
bs_update_record =
	{ syntax_title         = "record update"
787
	, syntax_patterns      = map exact ["&", "\\|", "\\{.*&.*=.*\\}"]
Camil Staps's avatar
Camil Staps committed
788 789
	, syntax_code          =
		[ "{ r & f1=x, f2=y, ... } // Updates r by setting f1 to x, f2 to y, ..."
790
		, "{ MyRecord | r & f1=x, f2=y, ... } // explicitly stating the type"
Camil Staps's avatar
Camil Staps committed
791 792 793 794 795 796 797 798 799
		, "# r & f1=x, f2=y, ...   // Same as # r = {r & f1=x, f2=y, ...}" // See https://clean.cs.ru.nl/Clean_2.3
		]
	, syntax_description   = "Updates a record by creating a copy and replacing one or more fields."
	, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798049"]
	, syntax_examples      = []
	}

bs_where_class =
	{ syntax_title         = "where"
Camil Staps's avatar
Camil Staps committed
800
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
801 802 803
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces the members of a {{`class`}} definition."
	, syntax_doc_locations = [CLR 8 "6.1"   "_Toc311798056"]
804
	, syntax_examples      = [EX "class Arith a        // Class definition\nwhere\n\t(+) infixl 6 :: a a -> a\n\t(-) infixl 6 :: a a -> a"]
Camil Staps's avatar
Camil Staps committed
805 806 807
	}
bs_where_instance =
	{ syntax_title         = "where"
Camil Staps's avatar
Camil Staps committed
808
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
809 810 811
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces the implementation of an {{`instance`}}."
	, syntax_doc_locations = [CLR 8 "6.1"   "_Toc311798056"]
812 813 814 815 816 817 818
	, syntax_examples      =
		[ add_imports ["StdEnv"] $ EX $
		  ":: T = C Int\n" +
		  "instance + T\n" +
		  "where\n" +
		  "\t(+) (C x) (C y) = C (x+y)"
		]
Camil Staps's avatar
Camil Staps committed
819 820 821
	}
bs_where_local =
	{ syntax_title         = "where"
Camil Staps's avatar
Camil Staps committed
822
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
823 824 825
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces local definitions. For guard-local definitions, see {{`with`}}."
	, syntax_doc_locations = [CLR 5 "3.5.2" "_Toc311798004"]
826 827 828 829 830 831 832
	, syntax_examples      =
		[ add_imports ["StdEnv"] $
		  EXs "macro" $
		  "primes = sieve [2..] // Local definitions\n" +
		  "where\n" +
		  "\tsieve [pr:r] = [pr:sieve (filter (\\n -> n rem pr <> 0) r)]"
		]
Camil Staps's avatar
Camil Staps committed
833 834 835 836
	}

bs_with =
	{ syntax_title         = "with"
Camil Staps's avatar
Camil Staps committed
837
	, syntax_patterns      = map exact ["with"]
Camil Staps's avatar
Camil Staps committed
838 839 840
	, syntax_code          = ["with"]
	, syntax_description   = "Introduces guard-local definitions. For function-local definitions, see {{`where`}}."
	, syntax_doc_locations = [CLR 5 "3.5.3" "_Toc311798005"]
841 842 843 844 845 846 847 848 849 850
	, syntax_examples      =
		[ add_imports ["StdEnv"] $
		  EXs "macro" $
		  "f g x y\n" +
		  "| x < 0 = g local\n" +
		  "\twith local = x + y\n" +
		  "| x > 0 = g local\n" +
		  "\twith local = x - y\n" +
		  "| otherwise = g 0"
		]
Camil Staps's avatar
Camil Staps committed
851 852 853 854
	}

bs_zf =
	{ syntax_title         = "list comprehension"
855
	, syntax_patterns      = map exact ["ZF-expression", "ZF", "zf", "*comprehension", "<-", "<\\|-", "<-:", "\\\\\\\\", ",", "&", "\\|", "let"]
856
	, syntax_code          =
857 858 859
		[ "[... \\\\ ... <- ...]"
		, "{... \\\\ ... <- ...}"
		]
860
	, syntax_description   = "Constructs a list or array composed of elements drawn from other lists or arrays. It is possible to use local definitions as well (see {{`let`}})."
861
	, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798024", CLR 6 "4.4.1" "_Toc311798032"]
862
	, syntax_examples      = map (add_imports ["StdEnv", "StdMaybe"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
863
		[ "cartesian    = [(x,y) \\\\ x <- [1,2,3], y <- [10,20]] // Cartesian product: (1,10), (1,20), (2,10), (2,20), (3,10), (3,20)"
Camil Staps's avatar
Camil Staps committed
864 865 866
		, "zip xs ys    = [(x,y) \\\\ x <- xs & y <- ys] // Pairwise zip through the lists"
		, "filter f xs  = [x \\\\ x <- xs | f x]         // Guard to add conditions"
		, "catMaybes ms = [x \\\\ Just x <- ms]          // Pattern matching in the selector"
Camil Staps's avatar
Camil Staps committed
867
		, "triangle     = [(x,y) \\\\ x <- [1,2,3], y <- [1..x]]  // Reusing x in the next generator: (1,1), (2,1), (2,2), (3,1), (3,2), (3,3)"
Camil Staps's avatar
Camil Staps committed
868 869 870 871 872 873 874 875
		, "arrToList a  = [x \\\\ x <-: a]               // <-: to draw elements from an array"
		, "listToArr l  = {x \\\\ x <- l}                // {..} to create an array"
		, "castList xs  = [|x \\\\ x <|- xs]             // The two pipe characters make both xs and the result overloaded lists"
		] ++
		[ add_imports ["StdEnv"] $ EXs "rhs" $
		  "[ sx \\\\ x <- [0..]\n" +
		  "\t, let sx = toString x                   // The let must end with a newline\n" +
		  "\t]"
Camil Staps's avatar
Camil Staps committed
876 877
		]
	}