Syntax.icl 39.6 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 167 168 169
	, 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"]
	, syntax_examples      = []
	}

170
bs_context =
Camil Staps's avatar
Camil Staps committed
171
	{ syntax_title         = "type context"
172 173 174 175 176 177 178 179 180
	, 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
181 182 183
		, "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."
184 185
		]
	, syntax_doc_locations = [CLR 8 "6.2" "_Toc311798057"]
186 187 188 189 190 191 192 193
	, 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"
194 195 196
		]
	}

Camil Staps's avatar
Camil Staps committed
197 198
bs_define_constant =
	{ syntax_title         = "graph definition"
Camil Staps's avatar
Camil Staps committed
199
	, syntax_patterns      = map exact ["=:"]
Camil Staps's avatar
Camil Staps committed
200 201 202 203 204 205
	, 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"]
206
	, syntax_examples      = [add_imports ["StdEnum"] $ EXs "macro" "mylist =: [1..10000]"]
Camil Staps's avatar
Camil Staps committed
207 208 209
	}
bs_define_graph =
	{ syntax_title         = "constant function definition"
Camil Staps's avatar
Camil Staps committed
210
	, syntax_patterns      = map exact ["=>"]
Camil Staps's avatar
Camil Staps committed
211 212
	, syntax_code          = ["... => ..."]
	, syntax_description   =
Camil Staps's avatar
Camil Staps committed
213
		"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
214 215 216
		"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"]
217
	, syntax_examples      = [add_imports ["StdEnum"] $ EXs "macro" "mylist => [1..10000]"]
Camil Staps's avatar
Camil Staps committed
218 219 220 221
	}

bs_dotdot =
	{ syntax_title         = "dotdot expression"
Camil Staps's avatar
Camil Staps committed
222
	, syntax_patterns      = map exact ["\\[\\w\\.\\.\\]", "\\[\\w\\.\\.\\w\\]", "\\[\\w,\\w\\.\\.\\]", "\\[\\w,\\w\\.\\.\\w\\]", "dotdot", "dot-dot", "\\.\\."]
Camil Staps's avatar
Camil Staps committed
223 224 225 226 227
	, 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"]
228
	, syntax_examples      = map (add_imports ["StdEnum"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
229 230 231 232 233 234 235 236 237
		[ "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"
Camil Staps's avatar
Camil Staps committed
238
	, syntax_patterns      = map exact ["E", "E\\.*"]
Camil Staps's avatar
Camil Staps committed
239 240 241
	, 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"]
242
	, 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
243 244
	}

Camil Staps's avatar
Camil Staps committed
245 246
bs_extensible_adt =
	{ syntax_title         = "extensible algebraic data type"
Camil Staps's avatar
Camil Staps committed
247
	, syntax_patterns      = map exact ["\\.\\.", "\\|"]
Camil Staps's avatar
Camil Staps committed
248 249 250 251 252
	, 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
253
		, "It is not possible to derive generic functions for EADTs."
Camil Staps's avatar
Camil Staps committed
254
		]
Mart Lubbers's avatar
Mart Lubbers committed
255
	, syntax_doc_locations = []
256 257 258 259 260 261 262
	, 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
263 264 265
		]
	}

Camil Staps's avatar
Camil Staps committed
266 267
bs_forall =
	{ syntax_title         = "universal quantifier"
Camil Staps's avatar
Camil Staps committed
268
	, syntax_patterns      = map exact ["A", "A\\.*"]
Camil Staps's avatar
Camil Staps committed
269 270 271
	, 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"]
272 273
	, 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']"
274
		, ":: T = C (A.a: a -> a)        // In a type"
275
		, "hd :: A.a: [a] -> a           // Not allowed: A. on the topmost level"
Camil Staps's avatar
Camil Staps committed
276 277 278
		]
	}

Mart Lubbers's avatar
Mart Lubbers committed
279 280
bs_foreign =
	{ syntax_title         = "foreign export"
Camil Staps's avatar
Camil Staps committed
281
	, syntax_patterns      = map exact ["foreign", "export", "ccall", "stdcall"]
Mart Lubbers's avatar
Mart Lubbers committed
282 283 284 285
	, syntax_code          =
		[ "foreign export [ccall | stdcall] ..."
		]
	, syntax_description   =
Camil Staps's avatar
Camil Staps committed
286
		"Exports the Clean function symbol to the binary.\n\n" +
Mart Lubbers's avatar
Mart Lubbers committed
287
		"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
288
	, syntax_doc_locations = [CLR 13 "11.1" "_Toc311798114"]
289
	, syntax_examples      = map EX
Mart Lubbers's avatar
Mart Lubbers committed
290 291 292
		[ "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
293
	}
Mart Lubbers's avatar
Mart Lubbers committed
294

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

Camil Staps's avatar
Camil Staps committed
312 313 314 315
bs_function_definition =
	{ syntax_title         = "function definition"
	, syntax_patterns      = map exact ["="]
	, syntax_code          = ["... = ..."]
Camil Staps's avatar
Camil Staps committed
316 317 318 319 320
	, 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
321 322 323 324 325 326
	, 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
327 328 329 330 331 332 333 334 335 336 337 338 339
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"]
340
	, syntax_examples      = map (add_imports ["StdEnv"] o EX)
Camil Staps's avatar
Camil Staps committed
341 342 343 344
		[ "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
345 346
bs_generic =
	{ syntax_title         = "generic function definition"
347
	, syntax_patterns      = map exact ["generic", "derive", "of", "with", "\\{\\|.*\\|\\}", "\\*!"]
Mart Lubbers's avatar
Mart Lubbers committed
348
	, syntax_code          = ["generic ... ... [| ...] [*!] :: ... ", "derive ... ... [of ...] [with ...]"]
349 350 351 352 353
	, 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
354
	, syntax_doc_locations = [CLR 9 "7.2" "_Toc311798069"]
355 356 357 358
	, 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" +
359
		  "gEq{|PAIR|} fx fy (PAIR x1 y1) (PAIR x2 y2) = fx x1 x2 && fy y1 y2"
360 361 362 363 364 365 366 367 368 369 370 371
		, 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
372 373 374
		]
	}

Camil Staps's avatar
Camil Staps committed
375 376 377 378 379 380 381 382 383
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
384 385
bs_import =
	{ syntax_title         = "imports"
Camil Staps's avatar
Camil Staps committed
386
	, syntax_patterns      = map exact ["import", "from", "qualified", "as", "=>", "code", "library"]
Camil Staps's avatar
Camil Staps committed
387 388 389 390 391 392 393 394 395 396 397 398
	, 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"]
399
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
400 401 402 403 404 405
		[ "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."
406 407 408
		] ++ 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
409 410 411 412 413
		]
	}

bs_infix =
	{ syntax_title         = "infix operator"
Camil Staps's avatar
Camil Staps committed
414
	, syntax_patterns      = map exact ["infix", "infixl", "infixr"]
Camil Staps's avatar
Camil Staps committed
415 416 417 418 419 420 421
	, 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      =
422 423 424
		[ 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
425 426 427 428 429
		]
	}

bs_instance =
	{ syntax_title         = "instance"
Camil Staps's avatar
Camil Staps committed
430
	, syntax_patterns      = map exact ["instance"]
Camil Staps's avatar
Camil Staps committed
431 432 433
	, syntax_code          = ["instance ... ... where ..."]
	, syntax_description   = "Defines an instantiation of a {{class}} for a type."
	, syntax_doc_locations = [CLR 8 "6.1" "_Toc311798056"]
434
	, syntax_examples      = map (add_imports ["StdOverloaded"] o EX)
Camil Staps's avatar
Camil Staps committed
435 436 437 438 439 440 441
		[ "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
442
	, syntax_patterns      = map exact ["lambda", "=", "->", "\\."]
Camil Staps's avatar
Camil Staps committed
443 444 445
	, syntax_code          = ["\\... -> ...", "\\... . ...", "\\... = ..."]
	, syntax_description   = "An anonymous, inline function."
	, syntax_doc_locations = [CLR 5 "3.4.1" "_Toc311798000"]
446
	, syntax_examples      = map (add_imports ["StdList"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
447 448 449 450 451 452 453 454
		[ "(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
455
	, syntax_patterns      = map exact [";", "\\{", "\\}"]
Camil Staps's avatar
Camil Staps committed
456 457 458 459 460 461
	, 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"]
462
	, syntax_examples      = [EX $
Camil Staps's avatar
Camil Staps committed
463 464 465 466 467 468 469 470 471 472 473 474 475
		"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
476
	, syntax_patterns      = map exact ["let", "in", "let in"]
Camil Staps's avatar
Camil Staps committed
477 478 479 480
	, syntax_code          = ["let ... in ..."]
	, syntax_description   = "An expression that introduces new scope."
	, syntax_doc_locations = [CLR 5 "3.5.1" "_Toc311798003"]
	, syntax_examples      =
481 482 483 484 485 486 487 488 489
		[ 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
490 491 492 493
		]
	}
bs_let_before =
	{ syntax_title         = "let before"
Camil Staps's avatar
Camil Staps committed
494
	, syntax_patterns      = map exact ["#", "#!"]
Camil Staps's avatar
Camil Staps committed
495 496 497 498
	, 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      =
499 500 501 502 503 504 505
		[ 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
506 507 508 509 510
		]
	}

bs_list_expressions =
	{ syntax_title         = "list expression"
Camil Staps's avatar
Camil Staps committed
511
	, syntax_patterns      = map exact ["list", "\\[\\]", "\\[:\\]", ":", "\\[\\w:\\w\\]", "\\['.*"]
Camil Staps's avatar
Camil Staps committed
512 513 514 515 516 517
	, 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"]
518
	, syntax_examples      = map (EXs "macro")
Camil Staps's avatar
Camil Staps committed
519
		[ "abc = ['a', 'b', 'c']     // Individual elements"
520 521 522
		, "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
523 524 525 526 527
		]
	}

bs_macro =
	{ syntax_title         = "macro"
Camil Staps's avatar
Camil Staps committed
528
	, syntax_patterns      = map exact [":==", "macro"]
Camil Staps's avatar
Camil Staps committed
529 530 531 532 533
	, 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"]
534
	, syntax_examples      = map (EXs "macro")
Camil Staps's avatar
Camil Staps committed
535 536 537 538 539 540 541 542
		[ "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
543
	, syntax_patterns      = map exact ["module", "definition", "implementation", "system", "definition module", "implementation module", "system module"]
Camil Staps's avatar
Camil Staps committed
544 545 546
	, 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"]
547
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
548
		[ "definition module StdList     // Exported definitions of list functions"
Camil Staps's avatar
Camil Staps committed
549 550 551 552 553 554 555
		, "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 =
556
	{ syntax_title         = "newtype definition"
Camil Staps's avatar
Camil Staps committed
557
	, syntax_patterns      = map exact ["=:", "newtype"]
Camil Staps's avatar
Camil Staps committed
558 559 560 561 562
	, 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      =
563 564
		[ EX ":: T =: T Int"
		, EX ":: T a =: T a"
Camil Staps's avatar
Camil Staps committed
565 566 567 568
		]
	}

bs_overloaded_type_variable =
569
	{ syntax_title         = "overloaded type variable"
Camil Staps's avatar
Camil Staps committed
570
	, syntax_patterns      = map exact ["\\^", "\\w\\^"]
Camil Staps's avatar
Camil Staps committed
571 572 573
	, 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"]
574 575 576 577 578 579 580
	, 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
581 582 583
	}

bs_pattern_named =
584
	{ syntax_title         = "pattern match"
Camil Staps's avatar
Camil Staps committed
585
	, syntax_patterns      = map exact ["=:"]
Camil Staps's avatar
Camil Staps committed
586 587 588
	, 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"]
589
	, syntax_examples      = map (add_imports ["StdMaybe"] o EX)
590 591
		[ "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
592 593 594
		]
	}

595 596
bs_pattern_predicate =
	{ syntax_title         = "pattern predicate"
Camil Staps's avatar
Camil Staps committed
597
	, syntax_patterns      = map exact ["=:"]
598 599 600 601 602 603 604 605 606 607 608 609
	, 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"]
	}

610 611 612 613 614 615
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 = []
616 617 618 619 620
	, 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]"
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
		]
	}

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
637 638
bs_selection_array =
	{ syntax_title         = "array selection"
Camil Staps's avatar
Camil Staps committed
639
	, syntax_patterns      = map exact ["\\.\\[\\]", "\\.\\[.*\\]", "\\.\\[,.*\\]", "\\.\\[.*,.*\\]"]
Camil Staps's avatar
Camil Staps committed
640 641 642
	, 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"]
643 644 645
	, 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
646 647 648 649
		]
	}
bs_selection_array_unique =
	{ syntax_title         = "unique array selection"
Camil Staps's avatar
Camil Staps committed
650
	, syntax_patterns      = map exact ["!\\[\\]", "!\\[.*\\]", "!\\[,.*\\]", "!\\[.*,.*\\]"]
Camil Staps's avatar
Camil Staps committed
651 652 653
	, 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"]
654 655 656
	, 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
657 658 659 660
		]
	}
bs_selection_record =
	{ syntax_title         = "record selection"
Camil Staps's avatar
Camil Staps committed
661
	, syntax_patterns      = map exact ["\\."]
Camil Staps's avatar
Camil Staps committed
662 663 664
	, syntax_code          = ["."]
	, syntax_description   = "Select a field from a (possibly multilevel) record."
	, syntax_doc_locations = [CLR 7 "5.2.1" "_Toc311798050"]
665 666 667 668 669
	, 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
670 671 672 673 674 675 676
		[ "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
677
	, syntax_patterns      = map exact ["!"]
Camil Staps's avatar
Camil Staps committed
678 679 680
	, 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"]
681 682 683 684 685
	, 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
686 687 688 689 690 691 692 693 694
		[ "(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
695
	, syntax_patterns      = map exact ["strict", "!"]
Camil Staps's avatar
Camil Staps committed
696 697 698
	, 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"]
699
	, syntax_examples      = [EX "acker :: !Int !Int -> Int"]
Camil Staps's avatar
Camil Staps committed
700 701 702 703
	}

bs_synonym =
	{ syntax_title         = "synonym type definition"
Camil Staps's avatar
Camil Staps committed
704
	, syntax_patterns      = map exact ["synonym", ":=="]
Camil Staps's avatar
Camil Staps committed
705 706 707
	, syntax_code          = [":: ... :== ..."]
	, syntax_description   = "Defines a new type name for an existing type."
	, syntax_doc_locations = [CLR 7 "5.3" "_Toc311798052"]
708
	, syntax_examples      = [EX ":: String :== {#Char}"]
Camil Staps's avatar
Camil Staps committed
709 710 711
	}
bs_synonym_abstract =
	{ syntax_title         = "abstract synonym type definition"
Camil Staps's avatar
Camil Staps committed
712
	, syntax_patterns      = map exact ["synonym", ":=="]
Camil Staps's avatar
Camil Staps committed
713 714 715
	, 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"]
716
	, syntax_examples      = [EX ":: Stack a (:== [a])"]
Camil Staps's avatar
Camil Staps committed
717 718
	}

Camil Staps's avatar
Camil Staps committed
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
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]"
		]
	}

743 744
bs_unique =
	{ syntax_title         = "uniqueness annotation"
Camil Staps's avatar
Camil Staps committed
745
	, syntax_patterns      = map exact ["\\*", "\\.", "\\w:", "\\[.*<=.*\\]", ",", "<="]
746
	, syntax_code          =
Camil Staps's avatar
Camil Staps committed
747 748
		[ "*..."
		, ". ..."
Camil Staps's avatar
Camil Staps committed
749
		, "...:..., [...<=...], [...<=...], ..."
Camil Staps's avatar
Camil Staps committed
750 751 752
		]
	, syntax_description   = join " "
		[ "Annotates a type with its uniqueness."
Camil Staps's avatar
Camil Staps committed
753 754 755 756 757 758 759
		, "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
760
		]
761
	, syntax_doc_locations = [CLR 11 "9.1" "_Toc311798093"]
762
	, syntax_examples      = map (add_imports ["StdEnv"] o EX)
763 764 765 766
		[ "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"
767 768 769
		]
	}

Camil Staps's avatar
Camil Staps committed
770 771
bs_update_array =
	{ syntax_title         = "array update"
Camil Staps's avatar
Camil Staps committed
772
	, syntax_patterns      = map exact ["&", "\\{.*&.*\\[.*].*=.*\\}"]
Camil Staps's avatar
Camil Staps committed
773
	, syntax_code          =
774 775 776
		[ "{ 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
777 778 779 780 781 782 783
		]
	, 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"
784
	, syntax_patterns      = map exact ["&", "\\|", "\\{.*&.*=.*\\}"]
Camil Staps's avatar
Camil Staps committed
785 786
	, syntax_code          =
		[ "{ r & f1=x, f2=y, ... } // Updates r by setting f1 to x, f2 to y, ..."
787
		, "{ MyRecord | r & f1=x, f2=y, ... } // explicitly stating the type"
Camil Staps's avatar
Camil Staps committed
788 789 790 791 792 793 794 795 796
		, "# 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
797
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
798 799 800
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces the members of a {{`class`}} definition."
	, syntax_doc_locations = [CLR 8 "6.1"   "_Toc311798056"]
801
	, 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
802 803 804
	}
bs_where_instance =
	{ syntax_title         = "where"
Camil Staps's avatar
Camil Staps committed
805
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
806 807 808
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces the implementation of an {{`instance`}}."
	, syntax_doc_locations = [CLR 8 "6.1"   "_Toc311798056"]
809 810 811 812 813 814 815
	, 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
816 817 818
	}
bs_where_local =
	{ syntax_title         = "where"
Camil Staps's avatar
Camil Staps committed
819
	, syntax_patterns      = map exact ["where"]
Camil Staps's avatar
Camil Staps committed
820 821 822
	, syntax_code          = ["where"]
	, syntax_description   = "Introduces local definitions. For guard-local definitions, see {{`with`}}."
	, syntax_doc_locations = [CLR 5 "3.5.2" "_Toc311798004"]
823 824 825 826 827 828 829
	, 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
830 831 832 833
	}

bs_with =
	{ syntax_title         = "with"
Camil Staps's avatar
Camil Staps committed
834
	, syntax_patterns      = map exact ["with"]
Camil Staps's avatar
Camil Staps committed
835 836 837
	, syntax_code          = ["with"]
	, syntax_description   = "Introduces guard-local definitions. For function-local definitions, see {{`where`}}."
	, syntax_doc_locations = [CLR 5 "3.5.3" "_Toc311798005"]
838 839 840 841 842 843 844 845 846 847
	, 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
848 849 850 851
	}

bs_zf =
	{ syntax_title         = "list comprehension"
Camil Staps's avatar
Camil Staps committed
852
	, syntax_patterns      = map exact ["ZF-expression", "ZF", "zf", "*comprehension", "<-", "<\\|-", "<-:", "\\\\\\\\", ",", "&", "\\|"]
853
	, syntax_code          =
854 855 856
		[ "[... \\\\ ... <- ...]"
		, "{... \\\\ ... <- ...}"
		]
857
	, syntax_description   = "Constructs a list or array composed of elements drawn from other lists or arrays."
858
	, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798024", CLR 6 "4.4.1" "_Toc311798032"]
859
	, syntax_examples      = map (add_imports ["StdEnv", "StdMaybe"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
860 861 862 863 864
		[ "cartesian    = [(x,y) \\\\ x <- [1,2,3], y <- [10,20]] // Cartesian product: (1,10), (1,20), (2,10), (2,20), (3,10), (3,20)"
		, "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"
		, "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)"
865 866
		, "arrToList a  = [x \\\\ x <-: a]                        // <-: to draw elements from an array"
		, "listToArr l  = {x \\\\ x <- l}                         // {..} to create an array"
Camil Staps's avatar
Camil Staps committed
867 868 869
		, "castList xs  = [|x \\\\ x <|- xs]                      // The two pipe characters make both xs and the result overloaded lists"
		]
	}