1
1
import PeachError from './errors'
2
2
import { isArray , isEqual } from './array'
3
+ import { zip } from './util'
4
+ import { TypedNode , TypedLiteralNode , TypedDestructuredArrayNode , Value , isTypedLiteralNode } from './node-types'
5
+
6
+ // FIXME tagged union - with didMatch: false, there are never bindings.
7
+ type binding = { [ name : string ] : Value }
3
8
4
- // FIXME union type - with didMatch: false, there are never bindings.
5
9
interface unification {
6
10
didMatch : boolean ,
7
- bindings : object
11
+ bindings : binding
8
12
}
9
13
10
- export default function unify ( patterns , values ) : unification {
14
+ export default function unify ( patterns : TypedNode [ ] , values : Value [ ] ) : unification {
11
15
if ( patterns . length !== values . length ) {
12
16
return didNotMatch
13
17
}
@@ -25,24 +29,23 @@ export default function unify (patterns, values) : unification {
25
29
return didMatch ( bindings )
26
30
}
27
31
28
- function unifyOne ( pattern , value ) {
29
- // TODO value equality operator
30
- if ( isValue ( pattern ) && pattern . value === value ) {
32
+ function unifyOne ( pattern : TypedNode , value : Value ) : binding {
33
+ if ( isTypedLiteralNode ( pattern ) && pattern . value === value ) {
31
34
// the pattern matched, but there is nothing to bind
32
35
return { }
33
36
}
34
37
35
- if ( isName ( pattern ) ) {
38
+ if ( pattern . type === 'Name' ) {
36
39
// the pattern matched; return a new binding
37
40
return { [ pattern . name ] : value }
38
41
}
39
42
40
43
// TODO generic value equality
41
- if ( isArray ( pattern ) && isEqual ( pattern . values , value ) ) {
44
+ if ( pattern . type === 'Array' && isEqual ( pattern . values , value ) ) {
42
45
return { }
43
46
}
44
47
45
- if ( isDestructuredArray ( pattern ) ) {
48
+ if ( pattern . type === 'DestructuredArray' ) {
46
49
return destructure ( pattern , value )
47
50
}
48
51
@@ -51,14 +54,14 @@ function unifyOne (pattern, value) {
51
54
}
52
55
53
56
// TODO this will need to change when Array is a wrapped type
54
- function destructure ( { head, tail } , array ) {
55
- if ( array . length === 0 ) {
57
+ function destructure ( { head, tail } : TypedDestructuredArrayNode , values : Value [ ] ) : binding {
58
+ if ( values . length === 0 ) {
56
59
throw new PeachError ( `Empty arrays cannot be destructured because they don't have a head` )
57
60
}
58
61
59
- const boundHead = unifyOne ( head , array [ 0 ] )
62
+ const boundHead = unifyOne ( head , values [ 0 ] )
60
63
if ( boundHead !== null ) {
61
- const boundTail = unifyOne ( tail , array . slice ( 1 ) )
64
+ const boundTail = unifyOne ( tail , values . slice ( 1 ) )
62
65
if ( boundTail ) {
63
66
return Object . assign ( boundHead , boundTail )
64
67
}
@@ -67,33 +70,14 @@ function destructure ({ head, tail }, array) {
67
70
return null
68
71
}
69
72
70
- const didNotMatch : unification = {
73
+ const didNotMatch : unification = {
71
74
didMatch : false ,
72
75
bindings : { }
73
76
}
74
77
75
- function didMatch ( bindings ) : unification {
78
+ function didMatch ( bindings : binding ) : unification {
76
79
return {
77
80
didMatch : true ,
78
81
bindings
79
82
}
80
83
}
81
-
82
- // TODO these belong with type definitions
83
- function isName ( { type } ) {
84
- return type === 'Name'
85
- }
86
-
87
- function isValue ( { type } ) {
88
- return [ 'Bool' , 'Str' , 'Numeral' ] . includes ( type )
89
- }
90
-
91
- function isDestructuredArray ( { type } ) {
92
- return type === 'DestructuredArray'
93
- }
94
-
95
- // TODO stdlib
96
- function zip ( arrayA , arrayB ) {
97
- return arrayA . map ( ( e , i ) => [ e , arrayB [ i ] ] )
98
- }
99
-
0 commit comments