@@ -15,3 +15,480 @@ A small strongly, statically typed compile-to-JS language with basic extensible
1515- Functions with multiple arguments
1616- Pattern matching
1717- Simple FFI
18+
19+## License
20+
21+See the `LICENSE` file
22+
23+## Installation
24+
25+Install the Haskell Plaform, then `cabal install`
26+
27+## Usage
28+
29+The `psc` executable takes a list of PureScript source files as arguments and by default writes out its errors or output to the console.
30+
31+The following options are supported:
32+
33+ -o --output
34+ Write the generated Javascript to the specified file
35+
36+ -e --externs
37+ Write a list of externs declarations to the specified file in addition to generating Javascript output
38+
39+## Motivation
40+
41+I was looking for a simple functional language which would compile to JavaScript and have the following characteristics:
42+
43+- Generate simple readable Javascript
44+- Provide the ability to compile to tight loops if necessary
45+- Reasonable type system
46+- Ideally, written in a programming language I would enjoy working in
47+- Provides a simple interface to existing Javascript code
48+
49+I didn't find exactly what I was looking for, so I wrote PureScript. It doesn't have everything right now, but it should serve as a simple core on which to develop new ideas.
50+
51+PureScript is *not* designed to be a general-purpose programming language. The primary use case is as a generator for purely-functional core libraries, with the main application code written in another language.
52+
53+PureScript can also be seen as a trade-off between a theoretically ideal language and one which generates reasonably high performance code.
54+
55+## First Example
56+
57+The following code defines a `Person` data type and a function to generate a string representation for a `Person`:
58+
59+ data Person = Person
60+ { name :: String
61+ , age :: Number
62+ }
63+
64+ extern itoa :: Number -> String
65+
66+ showPerson :: Person -> String
67+ showPerson = \p -> case p of
68+ Person o -> o.name ++ ", aged " ++ itoa(o.age)
69+
70+Line by line, this reads as follows:
71+
72+- `Person` is a data type with one constructor, also called `Person`
73+ - The `Person` constructor takes an object with two properties, `name` which is a `String`, and `age` which is a `Number`
74+- The `itoa` function is written in Javascript, and takes a `Number` and returns a `String`
75+- The `showPerson` function takes a `Person` and returns a `String`
76+- `showPerson` works by case analysis on its argument `p`, first matching the constructor `Person` and then using string concatenation and object accessors to return its result.
77+
78+The generated Javascript looks like this:
79+
80+ var Person = function (value) {
81+ return { ctor: 'Person', value: value };
82+ };
83+
84+ var showPerson = function (p) {
85+ return (function (_0) {
86+ if (_0.ctor === "Person") {
87+ var _1 = _0.value;
88+ var o = _1;
89+ return o.name ++ ", aged " ++ itoa(o.age);
90+ }
91+ throw "Failed pattern match";
92+ })(p);
93+ };
94+
95+## Type System
96+
97+The type system defines the following types:
98+
99+- Primitive Types
100+ - Number
101+ - String
102+ - Boolean
103+- Arrays
104+ - E.g. `[String]`, `[[Number]]`
105+- Records
106+ - E.g. `{ foo :: String ; bar :: Number }`
107+- Tagged Unions
108+ - E.g. `data Foo a = Foo | Bar String`
109+- Functions
110+ - E.g. `Number -> String`
111+ - E.g. `(Number, Number) -> Number`
112+ - Functions can have zero or more arguments
113+- Polymorphic types (for top level declarations only)
114+ - E.g. `forall a. a -> a`
115+
116+## Primitive Types
117+
118+The three primitive types `String`, `Number` and `Boolean` correspond to their Javascript equivalents at runtime.
119+
120+PureScript supports the same binary and unary operations on primitive types as Javascript, with the following exceptions:
121+
122+- String concatenation is denoted `++` to differentiate it from numeric addition, `+`
123+- PureScript's `==` and `!=` correspond to Javascript's strong equality tests `===` and `!==`
124+
125+Examples:
126+
127+ num = 1 + 2 * 3
128+ str = "Hello, " ++ "World!"
129+ bool = 1 > 2 || true
130+
131+## Arrays
132+
133+PureScript arrays correspond to Javascript arrays at runtime, but all elements must have the same type.
134+
135+Array literals look like Javascript array literals: `[1, 2, 3]
136+
137+Array elements can be read using array index notation `arr[0]`
138+
139+## Records
140+
141+PureScript records correspond to Javascript objects.
142+
143+Record literals look like Javascript object literals: `{ foo: "Foo" }`
144+
145+Properties can be read by using dot notation: `o.foo`
146+
147+## Tagged Unions
148+
149+Tagged unions consist of one or more constructors, each of which takes zero or one arguments.
150+
151+Tagged unions can only be created using their constructors, and deconstructed through pattern matching (see later).
152+
153+For example:
154+
155+ data Foo a = Foo | Bar String
156+
157+ runFoo = \foo -> case foo of
158+ Foo -> "It's a Foo"
159+ Bar s -> "It's a Bar. The string is " ++ s
160+
161+ runFoo Foo ++ runFoo (Bar "Test")
162+
163+In the example, Foo is a tagged union type which has two constructors. It's first constructor `Foo` takes no argument, and it's second `Bar` takes one, which must be a String.
164+
165+`runFoo` is an example of pattern matching on a tagged union type to discover its constructor, and the last line shows how `Foo`s are constructed.
166+
167+## Functions
168+
169+Functions in TypeScript can have zero or more arguments in general, just like in Javascript.
170+
171+Functions are introduced by using a backslash followed by a comma separated list of argument names:
172+
173+ test1 = \a, b, c -> a + b + c
174+
175+which would correspond to the Javascript `function test1(a, b, c) { return a + b + c; }`
176+
177+A function taking no arguments would look like this:
178+
179+ test2 = \ -> 100
180+
181+which would correspond to the Javascript `function test2() { return 100; }`
182+
183+Functions are applied by providing their arguments inside parentheses:
184+
185+ test1(1, 2, 3)
186+ test2()
187+
188+A special case is made in the case of functions with one argument. These functions can be applied without parentheses, and function application associates to the left:
189+
190+ -- has type Number -> Number -> Number -> Number
191+ addThree = \a -> \b -> \c -> a + b + c
192+
193+ -- has type Number -> Number -> Number
194+ addThree 1
195+
196+ -- has type Number -> Number
197+ addThree 1 2
198+
199+ -- has type Number
200+ addThree 1 2 3
201+
202+## Polymorphic Types
203+
204+Expressions defined at the top level may have polymorphic types.
205+
206+Here is an example:
207+
208+ identity = \x -> x
209+
210+`identity` is inferred to have (polymorphic) type `forall t0. t0 -> t0`. This means that for any type `t0`, `identity` can be given a value of type `t0` and will give back a value of the same type.
211+
212+A type annotation can also be provided:
213+
214+ identity :: forall a. a -> a
215+ identity = \x -> x
216+
217+Functions may also be polymorphic in row types or type variables with other kinds (see "Kind System"):
218+
219+ addProps = \o -> o.foo + o.bar
220+
221+Here, `addProps` is inferred to have type `forall r. { foo :: Number; bar :: Number | r } -> Number`. That is, it can take any type which has properties `Foo` and `Bar`, and *any other record properties*.
222+
223+So, the following compiles:
224+
225+ addProps { foo: 1, bar: 2, baz: 3 }
226+
227+but the following does not:
228+
229+ addProps { foo: 1 }
230+
231+since the `bar` property is missing.
232+
233+Again, a type annotation can be provided if necessary.
234+
235+## Type Inference
236+
237+All types can be inferred, but annotations can optionally be provided.
238+
239+## Kind System
240+
241+There are two primitive kinds, the kind of types and the kind of rows. Higher kinded types are also supported. That is, a type variable can refer to not only a type or a row, but a type constructor, or row constructor etc.
242+
243+## Whitespace
244+
245+Syntax is whitespace sensitive. The general rule of thumb is that declarations which span multiple lines should be indented past the column on which they were first defined on their subsequent lines.
246+
247+That is, the following is valid:
248+
249+ foo = bar(x) +
250+ baz(x)
251+
252+But this is not:
253+
254+ foo = bar(x) +
255+ baz(x)
256+
257+## Do Notation
258+
259+There is a keyword `do`, which does not have the same purpose as the `do` keyword in Haskell.
260+
261+`do` introduces a block. Blocks consist of statements, and must return a value of the same type on every branch of execution.
262+
263+The following types of statement are supported:
264+
265+- Variable introduction
266+- Variable assignment
267+- For loops
268+- For-each loops
269+- While loops
270+- If-Then-Else statements
271+
272+Here is an example of a power function defined using a block:
273+
274+ pow = \n, p -> do
275+ var m = n
276+ for i <- 0 until p:
277+ m = m * n
278+ return m
279+
280+Blocks enable local mutation of their variables, but mutation is not allowed in general. The type system prevents mutable variables from escaping their scope.
281+
282+That is, while the example above is valid, the following does not compile:
283+
284+ incr = \n -> do
285+ n = n + 1
286+ return n
287+
288+The variable `n` is not mutable, and so the assignment in the first line of the `do` block is not allowed.
289+
290+This function can be rewritten as follows:
291+
292+ incr = \n -> do
293+ var m = n
294+ m = m + 1
295+ return m
296+
297+Object properties and array elements can also be mutated inside a block. For example:
298+
299+ createObject = do
300+ var a = [1, 2, 3]
301+ a[1] = 4
302+ var o = { foo: [] }
303+ o.foo = a
304+ return o
305+
306+## For Loops
307+
308+For loops look like this:
309+
310+ total = do
311+ var n = 0
312+ for i <- 0 until 10:
313+ n = n + i
314+ return n
315+
316+The bounds `0` and `10` are inclusive and exclusive respectively.
317+
318+## For-Each Loops
319+
320+For each loops loop over the elements in an array using the `Object.forEach` method. A polyfill may be required for some browsers:
321+
322+ total = \arr -> do
323+ var n = 0
324+ foreach i in arr:
325+ n = n + i
326+ return n
327+
328+## While Loops
329+
330+The syntax of a while loop is similar to a foreach loop:
331+
332+ log2 = \n -> do
333+ var count = 0
334+ var m = n
335+ while m > 1:
336+ m = m / 2
337+ count = count + 1
338+ return count
339+
340+## If-Then-Else Statements
341+
342+Else branches are optional, and may contain further `if` statements, just as in Javascript:
343+
344+ collatz = \n -> do
345+ var count = 0
346+ var m = n
347+ while m > 1:
348+ if m % 2 == 0:
349+ m = m / 2
350+ else:
351+ m = m * 3 + 1
352+ count = count + 1
353+ return count
354+
355+## Pattern Matching
356+
357+Pattern matching deconstructs a value to bring zero or more expressions into scope. Pattern matches are introduced with the `case` keyword.
358+
359+Pattern matches have the following general form
360+
361+ case value of
362+ pattern -> result
363+ ...
364+ pattern -> result
365+
366+The following pattern types are supported:
367+
368+- Wildcard pattern
369+- Literal patterns
370+- Variable pattern
371+- Array patterns
372+- Record patterns
373+- Named patterns
374+- Guards
375+
376+Patterns need not be exhaustive. A pattern match failed exception will be thrown at runtime if no pattern matches the input.
377+
378+## Wildcard Patterns
379+
380+The wilcard `_` matches any input and brings nothing into scope:
381+
382+ case x of
383+ _ -> 0
384+
385+## Literal Patterns
386+
387+Literal patterns are provided to match on primitives:
388+
389+ case booleanValue of
390+ true -> 0
391+ false -> 1
392+
393+ case stringValue of
394+ "Foo" -> 0
395+ _ -> 1
396+
397+ case numericValue of
398+ 0 -> 0
399+ _ -> 1
400+
401+## Variable Pattern
402+
403+A variable pattern matches any input and binds that input to its name:
404+
405+ case foo(x) of
406+ result -> bar(result)
407+
408+## Array Patterns
409+
410+Array patterns match an input which is an array, and bring its elements into scope.
411+
412+For example:
413+
414+ f = \arr -> case arr of
415+ [x] -> x
416+ [x, y : xs] -> x * y + f(xs)
417+ _ -> 0
418+
419+Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope.
420+
421+The second pattern matches arrays with two or more elements, and brings the first and second elements into scope, along with the remainder of the array as the variable `xs`.
422+
423+## Record Patterns
424+
425+Record patterns match an input which is a record, and bring its properties into scope.
426+
427+ f = \o -> case o of
428+ { foo = "Foo" } -> o.bar
429+ _ -> 0
430+
431+## Nested Patterns
432+
433+The patterns above can be combined to create larger patterns.
434+
435+For example:
436+
437+ f = \o -> case o of
438+ { arr = [] } -> 0
439+ { arr = [x:_], take = "head" } -> x
440+ { arr = [_:xs], take = "tail" } -> sum xs
441+
442+## Named Patterns
443+
444+Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the `@` symbol:
445+
446+ f = \arr -> case arr of
447+ a@[_,_:_] -> a
448+ a -> a
449+
450+Here, in the first pattern, any array with two or more elements will be matched and bound to the variable `a`.
451+
452+## Guards
453+
454+Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern:
455+
456+ evens = \arr -> case arr of
457+ [] -> 0
458+ [x:xs] | x % 2 == 0 -> 1 + evens xs
459+ [_:xs] -> evens xs
460+
461+## Operators
462+
463+In addition to the standard operators, user-defined infix operators can be created by enclosing names in parentheses:
464+
465+E.g. to create a synonym for string concatenation:
466+
467+ (<>) = \s1 -> \s2 -> s1 ++ s2
468+
469+ greeting = "Hello" <> "World!"
470+
471+Regular functions can be used as operators by enclosing their names in backticks:
472+
473+ foo = \x -> \y -> x * y + y
474+
475+ test = 10 `foo` 20
476+
477+Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates:
478+
479+ infixl 5 <>
480+ infixr 7 %%
481+
482+## Foreign Function Interface
483+
484+The `extern` keyword declares a value which is defined in Javascript, and its type:
485+
486+ extern pow :: (Number, Number) -> Number
487+
488+To declare a new type with no constructors, use `extern data` and provide the kind:
489+
490+ extern IO :: * -> *
491+
492+ extern console :: {
493+ log :: String -> IO {}
494+ }