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
	, syntax_description   = "Lets you point the type checker to the type that is determined by the other types (undocumented and experimental)."
305
	, syntax_doc_locations = []
306 307
	, syntax_examples      = map (requires_itask_compiler o EX)
		[ "class plus a b ~c :: a b -> c\n" +
Camil Staps's avatar
Camil Staps committed
308
		  "instance plus Int Int Int where plus x y = x + y\n" +
309
		  "Start = plus 1 (plus 1 1) // Overloading can be resolved because we told the compiler that c is determined by the other types."
310 311 312
		]
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

bs_zf =
	{ syntax_title         = "list comprehension"
853
	, syntax_patterns      = map exact ["ZF-expression", "ZF", "zf", "*comprehension", "<-", "<\\|-", "<-:", "\\\\\\\\", ",", "&", "\\|", "let"]
854
	, syntax_code          =
855 856 857
		[ "[... \\\\ ... <- ...]"
		, "{... \\\\ ... <- ...}"
		]
858
	, 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`}})."
859
	, syntax_doc_locations = [CLR 6 "4.2.1" "_Toc311798024", CLR 6 "4.4.1" "_Toc311798032"]
860
	, syntax_examples      = map (add_imports ["StdEnv", "StdMaybe"] o EXs "macro")
Camil Staps's avatar
Camil Staps committed
861
		[ "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
862 863 864
		, "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
865
		, "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
866 867 868 869 870 871 872 873
		, "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
874 875
		]
	}