Syntax.icl 40.1 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
import Regex
Camil Staps's avatar
Camil Staps committed
14
exact s = fromOk (compileRegex (concat ["^",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 (add_imports ["StdEnv"] o requires_itask_compiler o EX)
		[ "class plus a b ~c :: a b -> c // c is determined by a and b"
308 309 310
		]
	}

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

Camil Staps's avatar
Camil Staps committed
374 375 376 377 378 379 380 381 382
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
383 384
bs_import =
	{ syntax_title         = "imports"
385
	, syntax_patterns      = map exact ["import", "from", "qualified", "as", "=>", "code", "library", "\\(\\)", "\\.\\."]
Camil Staps's avatar
Camil Staps committed
386 387 388 389 390 391 392 393 394 395 396 397
	, 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"]
398
	, syntax_examples      = map EX
Camil Staps's avatar
Camil Staps committed
399 400 401 402 403 404
		[ "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."
405 406 407 408 409
		] ++ map (add_imports ["StdEnv"] o EX)
		[ "from StdMaybe import :: Maybe          // Import only the type Maybe"
		, "from StdMaybe import :: Maybe(..)      // Import the type Maybe and all constructors"
		, "from StdMaybe import :: Maybe(Just)    // Import the type Maybe and the Just constructor"
		, "from Data.Foldable import class Foldable(foldr1()) // Import the class Foldable and the foldr1 member type"
410 411 412
		] ++ 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
413 414 415 416 417
		]
	}

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

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

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

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

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

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

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

614 615
bs_qualified_identifier =
	{ syntax_title         = "qualified identifier"
Camil Staps's avatar
Camil Staps committed
616
	, syntax_patterns      = map (fromOk o compileRegex) ["^'.+'", "^qualified$"]
617 618 619
	, syntax_code          = ["'...'. ..."]
	, syntax_description   = "The identifiers of {{`qualified`}} imports must be prepended with `'...'.`, where `...` is the name of the qualified import."
	, syntax_doc_locations = []
620 621 622 623 624
	, 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]"
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
		]
	}

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

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

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

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

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

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

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