(signature)
| 52 | exports.types = types |
| 53 | |
| 54 | function protocol(signature) { |
| 55 | /** |
| 56 | Defines new protocol that may be implemented for different types. |
| 57 | |
| 58 | ## Example |
| 59 | |
| 60 | var sequence = protocol.define(('Logical list abstraction', { |
| 61 | first: ('Returns the first item in the sequence', [ protocol ]), |
| 62 | rest: ('Returns a sequence of the items after the first', [ protocol ]), |
| 63 | stick: ('Returns a new sequence where item is first, and this is rest', [ Object, protocol ]) |
| 64 | })) |
| 65 | |
| 66 | **/ |
| 67 | function Protocol(type, methods) { |
| 68 | /** |
| 69 | Extends this protocol by implementing it for the given `type`. |
| 70 | |
| 71 | ## Example |
| 72 | |
| 73 | sequence(String, { |
| 74 | first: function(string) { return string[0] || null }, |
| 75 | rest: function(string) { return String.prototype.substr.call(string, 1) }, |
| 76 | stick: function(item, string) { return item + string } |
| 77 | }) |
| 78 | sequence(Array, { |
| 79 | first: function(array) { return array[0] || null }, |
| 80 | rest: function(array) { return Array.prototype.slice.call(array, 1) }, |
| 81 | stick: function(item, array) { |
| 82 | return Array.prototype.concat.call([ item ], array) |
| 83 | } |
| 84 | }) |
| 85 | **/ |
| 86 | var types = slice(arguments) |
| 87 | methods = types.pop() |
| 88 | if (!types.length) extend(Protocol, Default, methods) |
| 89 | else while (types.length) extend(Protocol, types.shift(), methods) |
| 90 | return type |
| 91 | } |
| 92 | |
| 93 | Protocol.signature = signature |
| 94 | var descriptor = {} |
| 95 | Object.keys(signature).forEach(function(key) { |
| 96 | function method() { |
| 97 | var index = method[':this-index'] |
| 98 | var name = method[':name'] |
| 99 | var target = arguments[index] |
| 100 | var type = typeOf(target) |
| 101 | var f = ( |
| 102 | (target && target[name]) || // By instance |
| 103 | (type in types && types[type][name]) || // By type |
| 104 | (type === 'Type' && types.Object[name]) || // By ancestor |
| 105 | (types.Default[name])) // Default |
| 106 | |
| 107 | if (!f) throw TypeError(ERROR_DOES_NOT_IMPLEMENTS + key) |
| 108 | return f.apply(f, arguments) |
| 109 | } |
| 110 | method[':this-index'] = signature[key].indexOf(protocol) |
| 111 | method[':name'] = Name(key) |
no test coverage detected