# Copyright 2018 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import os
import sys
import openwhisk
import copy
import inspect
from composer import __version__

# standard combinators

combinators = {
    'empty': {'since': '0.4.0'},
    'seq': {'components': True, 'since': '0.4.0'},
    'sequence': {'components': True, 'since': '0.4.0'},
    'if': {'args': [{'_': 'test'}, {'_': 'consequent'}, {'_': 'alternate', 'optional': True}], 'since': '0.4.0'},
    'if_nosave': {'args': [{'_': 'test'}, {'_': 'consequent'}, {'_': 'alternate', 'optional': True}], 'since': '0.4.0'},
    'while': {'args': [{'_': 'test'}, {'_': 'body'}], 'since': '0.4.0'},
    'while_nosave': {'args': [{'_': 'test'}, {'_': 'body'}], 'since': '0.4.0'},
    'dowhile': {'args': [{'_': 'body'}, {'_': 'test'}], 'since': '0.4.0'},
    'dowhile_nosave': {'args': [{'_': 'body'}, {'_': 'test'}], 'since': '0.4.0'},
    'try': {'args': [{'_': 'body'}, {'_': 'handler'}], 'since': '0.4.0'},
    'finally': {'args': [{'_': 'body'}, {'_': 'finalizer'}], 'since': '0.4.0'},
    'retain': {'components': True, 'since': '0.4.0'},
    'retain_catch': {'components': True, 'since': '0.4.0'},
    'let': {'args': [{'_': 'declarations', 'type': 'object'}], 'components': True, 'since': '0.4.0'},
    'mask': {'components': True, 'since': '0.4.0'},
    'action': {'args': [{'_': 'name', 'type': 'string'}, {'_': 'action', 'type': 'object', 'optional': True}], 'since': '0.4.0'},
    'composition': {'args': [{'_': 'name', 'type': 'string'}, {'_': 'composition'}], 'since': '0.4.0'},
    'repeat': {'args': [{'_': 'count', 'type': 'int'}], 'components': True, 'since': '0.4.0'},
    'retry': {'args': [{'_': 'count', 'type': 'int'}], 'components': True, 'since': '0.4.0'},
    'value': {'args': [{'_': 'value', 'type': 'value'}], 'since': '0.4.0'},
    'literal': {'args': [{'_': 'value', 'type': 'value'}], 'since': '0.4.0'},
    'function': {'args': [{'_': 'function', 'type': 'object'}], 'since': '0.4.0'}
}

class ComposerError(Exception):
    def __init__(self, message, *arguments):
       self.message = message
       self.argument = arguments

def serialize(obj):
    return obj.__dict__

class Composition:
    def __init__(self, **kwargs):
        if kwargs is not None:
            for k, v in kwargs.items():
                setattr(self, k, v)

    def __str__(self):
        return json.dumps(self.__dict__, indent=2, default=serialize)

    def visit(self, f):
        ''' apply f to all fields of type composition '''

        combinator = combinators[getattr(self, 'type')]
        if 'components' in combinator:
            self.components = tuple(map(lambda c: f(c, None), self.components))

        if 'args' in combinator:
            for arg in combinator['args']:
                if 'type' not in arg:
                    setattr(self, arg['_'], f(getattr(self, arg['_']), arg['_']))

class Compiler:

    def empty(self):
        return self._compose('empty', ())

    def literal(self, value):
        return self._compose('literal', (value,))

    def seq(self, *arguments):
        return self._compose('seq', arguments)

    def sequence(self, *arguments):
        return self._compose('sequence', arguments)

    def action(self, name, action=None):
        return self._compose('action', (name, action))

    def when(self, test, consequent, alternate=None):
        return self._compose('if', (test, consequent, alternate))

    def ensure(self, body, finalizer):
        return self._compose('finally', (body, finalizer))

    def task(self, task):
        '''detect task type and create corresponding composition object'''
        if task is None:
            return self.empty()

        if isinstance(task, Composition):
            return task

        if callable(task):
            return self.function(task)

        if isinstance(task, str): # python3 only
            return self.action(task)

        raise ComposerError('Invalid argument', task)

    def function(self, fun):
        ''' function combinator: stringify lambda code '''
        if callable(fun):
            try:
                fun = inspect.getsource(fun)
            except OSError:
                raise ComposerError('Invalid argument', fun)

        if isinstance(fun, str):
            fun = { 'kind': 'nodejs:default', 'code': fun }

        if not isinstance(fun, dict) or fun is None:
            raise ComposerError('Invalid argument', fun)

        return Composition(type='function', function={ 'exec': fun })

    def _compose(self, type_, arguments):
        combinator = combinators[type_]
        skip = len(combinator['args']) if 'args' in combinator else 0
        composition = Composition(type=type_)

        # process declared arguments
        for i in range(skip):
            arg = combinator['args'][i]
            argument = arguments[i] if len(arguments) > i else None

            if 'type' not in arg:
                setattr(composition, arg['_'], self.task(argument))
            elif arg['type'] == 'value':
                if type(argument).__name__ == 'function':
                    raise ComposerError('Invalid argument', argument)
                setattr(composition, arg['_'], argument)
            else:
                if type(argument).__name__ != arg['type']:
                    raise ComposerError('Invalid argument', argument)

                setattr(composition, arg['_'], argument)

        if 'components' in combinator:
            setattr(composition, 'components', tuple(map(lambda obj: self.task(obj), arguments[skip:])))

        return composition

    def deserialize(self, composition):
        ''' recursively deserialize composition '''

        composition = copy.copy(composition)
        composition.visit(lambda composition: self.deserialize(composition))
        return composition

    def label(self, composition):
        ''' label combinators with the json path '''

        if not isinstance(composition, Composition):
            raise ComposerError('Invalid argument', composition)

        def label(path):

            def labeler(composition, name, array) :
                nonlocal path
                composition = copy.copy(composition)
                segment = ''
                if name is not None:
                    if array is not None:
                        segment = '['+name+']'
                    else:
                        segment = '.'+name

                setattr(composition, 'path', path + segment)

                # label nested combinators
                composition.visit(label(getattr(composition, 'path')))
                return composition

            return labeler

        return label('')(composition, None, None)


    def lower(self, composition, combinators = []):
        ''' recursively label and lower combinators to the desired set of combinators (including primitive combinators) '''

        if not isinstance(composition, Composition):
            raise ComposerError('Invalid argument', composition)

        # TODO

        return composition


def parse_action_name(name):
    '''
      Parses a (possibly fully qualified) resource name and validates it. If it's not a fully qualified name,
      then attempts to qualify it.

      Examples string to namespace, [package/]action name
        foo => /_/foo
        pkg/foo => /_/pkg/foo
        /ns/foo => /ns/foo
        /ns/pkg/foo => /ns/pkg/foo
    '''
    if not isinstance(name, str):
        raise ComposerError('Name is not valid')
    name = name.strip()
    if len(name) == 0:
        raise ComposerError('Name is not specified')

    delimiter = '/'
    parts = name.split(delimiter)
    n = len(parts)
    leadingSlash = name[0] == delimiter if len(name) > 0 else False
    # no more than /ns/p/a
    if n < 1 or n > 4 or (leadingSlash and n == 2) or (not leadingSlash and n == 4):
        raise ComposerError('Name is not valid')

    # skip leading slash, all parts must be non empty (could tighten this check to match EntityName regex)
    for part in parts[1:]:
        if len(part.strip()) == 0:
            raise ComposerError('Name is not valid')

    newName = delimiter.join(parts)
    if leadingSlash:
        return newName
    elif n < 3:
        return delimiter+'_'+delimiter+newName
    else:
        return delimiter+newName

class Compositions:
    ''' management class for compositions '''
    def __init__(self, wsk, composer):
        self.actions = wsk.actions
        self.composer = composer

    def deploy(self, composition, combinators=None):
        if not isinstance(composition, Composition):
            raise ComposerError('Invalid argument', composition)

        if composition.type != 'composition':
            raise ComposerError('Cannot deploy anonymous composition')

        obj = self.composer.encode(composition, combinators)

        if 'actions' in obj:
            for action in obj['actions']:
                self.actions.delete(action)
                self.actions.update(action)

class Composer(Compiler):
    def action(self, name, options = {}):
        ''' enhanced action combinator: mangle name, capture code '''
        name = parse_action_name(name) # throws ComposerError if name is not valid
        exec = None
        if hasattr(options, 'sequence'): # native sequence
            exec = { 'kind': 'sequence', 'components': tuple(map(parse_action_name, options['sequence'])) }

        if hasattr(options, 'filename') and isinstance(options['filename'], str): # read action code from file
            raise ComposerError('read from file not implemented')
            # exec = fs.readFileSync(options.filename, { encoding: 'utf8' })

        # if (typeof options.action === 'function') { // capture function
        #     exec = `const main = ${options.action}`
        #     if (exec.indexOf('[native code]') !== -1) throw new ComposerError('Cannot capture native function', options.action)
        # }

        if hasattr(options, 'action') and (isinstance(options['action'], str) or isinstance(options['action'],  dict)):
            exec = options['action']

        if isinstance(exec, str):
            exec = { 'kind': 'nodejs:default', 'code': exec }

        return Composition(type='action', exec=exec, name=name)

    def openwhisk(self, options):
        ''' return enhanced openwhisk client capable of deploying compositions '''
        # try to extract apihost and key first from whisk property file file and then from os.environ

        wskpropsPath = os.environ['WSK_CONFIG_FILE'] if 'WSK_CONFIG_FILE' in os.environ else os.path.expanduser('~/.wskprops')
        with open(wskpropsPath) as f:
            lines = f.readlines()

        options = dict(options)

        for line in lines:
            parts = line.strip().split('=')
            if len(parts) == 2:
                if parts[0] == 'APIHOST':
                    options['apihost'] = parts[1]
                elif parts[0] == 'AUTH':
                    options['api_key'] = parts[1]


        if '__OW_API_HOST' in os.environ:
            options['apihost'] = os.environ['__OW_API_HOST']

        if '__OW_API_KEY' in os.environ:
             options['api_key'] = os.environ['__OW_API_KEY']

        wsk = openwhisk.Client(options)
        wsk.compositions = Compositions(wsk, self)
        return wsk


    def composition(self, name, composition):
        ''' enhanced composition combinator: mangle name '''

        if not isinstance(name, str):
            raise ComposerError('Invalid argument', name)

        name = parse_action_name(name)
        return Composition(type='composition', name=name, composition= self.task(composition))


    def encode(self, composition, combinators=[]):
        ''' recursively encode composition into { composition, actions }
            by encoding nested compositions into actions and extracting nested action definitions '''

        if not isinstance(composition, Composition):
            raise ComposerError('Invalid argument', composition)

        composition = self.lower(composition, combinators)

        actions = []

        def encode(composition, name):
            composition = copy.copy(composition)
            composition.visit(encode)
            if composition.type == 'composition':
                #code = '// generated by composer v'+__version__+'\n\nconst composition = '+str(encode(composition.composition, ''))+'\n\n// do not edit below this point\n\n'+_conductorCode+'('+_compilerCode+'())' # invoke conductor on composition
                code = '# generated by composer v'+__version__+'\n\ncomposition = '+str(encode(composition.composition, ''))+'\n\n# do not edit below this point\n\n'+_conductorCode+'('+_compilerCode+'())' # invoke conductor on composition
                composition.action = { 'exec': { 'kind': 'nodejs:default', 'code':code }, 'annotations': [{ 'key': 'conductor', 'value': str(composition.composition) }, { 'key': 'composer', 'value': __version__ }] }

                del composition.composition
                composition.type = 'action'

            if composition.type == 'action' and hasattr(composition, 'action'):
                actions.append({ 'name': composition.name, 'action': composition.action, 'serializer': serialize })
                del composition.action

            return composition


        composition = encode(composition, None)
        return { 'composition': composition, 'actions': actions }

# Use Node js server-side code
def conductorPyCode():
    with open('workfile') as f:
        read_data = f.read()

# Use Node js server-side code

_conductorCode = '''
const main=(function conductor({ Compiler }) {
    const compiler = new Compiler()

    this.require = require

    function chain(front, back) {
        front.slice(-1)[0].next = 1
        front.push(...back)
        return front
    }

    function sequence(components) {
        if (components.length === 0) return [{ type: 'empty' }]
        return components.map(compile).reduce(chain)
    }

    function compile(json) {
        const path = json.path
        switch (json.type) {
            case 'sequence':
                return chain([{ type: 'pass', path }], sequence(json.components))
            case 'action':
                return [{ type: 'action', name: json.name, path }]
            case 'function':
                return [{ type: 'function', exec: json.function.exec, path }]
            case 'finally':
                var body = compile(json.body)
                const finalizer = compile(json.finalizer)
                var fsm = [[{ type: 'try', path }], body, [{ type: 'exit' }], finalizer].reduce(chain)
                fsm[0].catch = fsm.length - finalizer.length
                return fsm
            case 'let':
                var body = sequence(json.components)
                return [[{ type: 'let', let: json.declarations, path }], body, [{ type: 'exit' }]].reduce(chain)
            case 'mask':
                var body = sequence(json.components)
                return [[{ type: 'let', let: null, path }], body, [{ type: 'exit' }]].reduce(chain)
            case 'try':
                var body = compile(json.body)
                const handler = chain(compile(json.handler), [{ type: 'pass' }])
                var fsm = [[{ type: 'try', path }], body, [{ type: 'exit' }]].reduce(chain)
                fsm[0].catch = fsm.length
                fsm.slice(-1)[0].next = handler.length
                fsm.push(...handler)
                return fsm
            case 'if_nosave':
                var consequent = compile(json.consequent)
                var alternate = chain(compile(json.alternate), [{ type: 'pass' }])
                var fsm = [[{ type: 'pass', path }], compile(json.test), [{ type: 'choice', then: 1, else: consequent.length + 1 }]].reduce(chain)
                consequent.slice(-1)[0].next = alternate.length
                fsm.push(...consequent)
                fsm.push(...alternate)
                return fsm
            case 'while_nosave':
                var consequent = compile(json.body)
                var alternate = [{ type: 'pass' }]
                var fsm = [[{ type: 'pass', path }], compile(json.test), [{ type: 'choice', then: 1, else: consequent.length + 1 }]].reduce(chain)
                consequent.slice(-1)[0].next = 1 - fsm.length - consequent.length
                fsm.push(...consequent)
                fsm.push(...alternate)
                return fsm
            case 'dowhile_nosave':
                var test = compile(json.test)
                var fsm = [[{ type: 'pass', path }], compile(json.body), test, [{ type: 'choice', then: 1, else: 2 }]].reduce(chain)
                fsm.slice(-1)[0].then = 1 - fsm.length
                fsm.slice(-1)[0].else = 1
                var alternate = [{ type: 'pass' }]
                fsm.push(...alternate)
                return fsm
        }
    }

    const fsm = compile(compiler.lower(compiler.label(compiler.deserialize(composition))))

    const isObject = obj => typeof obj === 'object' && obj !== null && !Array.isArray(obj)

    // encode error object
    const encodeError = error => ({
        code: typeof error.code === 'number' && error.code || 500,
        error: (typeof error.error === 'string' && error.error) || error.message || (typeof error === 'string' && error) || 'An internal error occurred'
    })

    // error status codes
    const badRequest = error => Promise.reject({ code: 400, error })
    const internalError = error => Promise.reject(encodeError(error))

    return params => Promise.resolve().then(() => invoke(params)).catch(internalError)

    // do invocation
    function invoke(params) {
        // initial state and stack
        let state = 0
        let stack = []

        // restore state and stack when resuming
        if (params.$resume !== undefined) {
            if (!isObject(params.$resume)) return badRequest('The type of optional $resume parameter must be object')
            state = params.$resume.state
            stack = params.$resume.stack
            if (state !== undefined && typeof state !== 'number') return badRequest('The type of optional $resume.state parameter must be number')
            if (!Array.isArray(stack)) return badRequest('The type of $resume.stack must be an array')
            delete params.$resume
            inspect() // handle error objects when resuming
        }

        // wrap params if not a dictionary, branch to error handler if error
        function inspect() {
            if (!isObject(params)) params = { value: params }
            if (params.error !== undefined) {
                params = { error: params.error } // discard all fields but the error field
                state = undefined // abort unless there is a handler in the stack
                while (stack.length > 0) {
                    if (typeof (state = stack.shift().catch) === 'number') break
                }
            }
        }

        // run function f on current stack
        function run(f) {
            // handle let/mask pairs
            const view = []
            let n = 0
            for (let frame of stack) {
                if (frame.let === null) {
                    n++
                } else if (frame.let !== undefined) {
                    if (n === 0) {
                        view.push(frame)
                    } else {
                        n--
                    }
                }
            }

            // update value of topmost matching symbol on stack if any
            function set(symbol, value) {
                const element = view.find(element => element.let !== undefined && element.let[symbol] !== undefined)
                if (element !== undefined) element.let[symbol] = JSON.parse(JSON.stringify(value))
            }

            // collapse stack for invocation
            const env = view.reduceRight((acc, cur) => typeof cur.let === 'object' ? Object.assign(acc, cur.let) : acc, {})
            let main = '(function(){try{'
            for (const name in env) main += `var ${name}=arguments[1]['${name}'];`
            main += `return eval((${f}))(arguments[0])}finally{`
            for (const name in env) main += `arguments[1]['${name}']=${name};`
            main += '}})'
            try {
                return (1, eval)(main)(params, env)
            } finally {
                for (const name in env) set(name, env[name])
            }
        }

        while (true) {
            // final state, return composition result
            if (state === undefined) {
                console.log(`Entering final state`)
                console.log(JSON.stringify(params))
                if (params.error) return params; else return { params }
            }

            // process one state
            const json = fsm[state] // json definition for current state
            if (json.path !== undefined) console.log(`Entering composition${json.path}`)
            const current = state
            state = json.next === undefined ? undefined : current + json.next // default next state
            switch (json.type) {
                case 'choice':
                    state = current + (params.value ? json.then : json.else)
                    break
                case 'try':
                    stack.unshift({ catch: current + json.catch })
                    break
                case 'let':
                    stack.unshift({ let: JSON.parse(JSON.stringify(json.let)) })
                    break
                case 'exit':
                    if (stack.length === 0) return internalError(`State ${current} attempted to pop from an empty stack`)
                    stack.shift()
                    break
                case 'action':
                    return { action: json.name, params, state: { $resume: { state, stack } } } // invoke continuation
                    break
                case 'function':
                    let result
                    try {
                        result = run(json.exec.code)
                    } catch (error) {
                        console.error(error)
                        result = { error: `An exception was caught at state ${current} (see log for details)` }
                    }
                    if (typeof result === 'function') result = { error: `State ${current} evaluated to a function` }
                    // if a function has only side effects and no return value, return params
                    params = JSON.parse(JSON.stringify(result === undefined ? params : result))
                    inspect()
                    break
                case 'empty':
                    inspect()
                    break
                case 'pass':
                    break
                default:
                    return internalError(`State ${current} has an unknown type`)
            }
        }
    }
})
'''

_compilerCode = '''
function compiler() {
    const util = require('util')
    const semver = require('semver')

    // standard combinators
    const combinators = {
        empty: { since: '0.4.0' },
        seq: { components: true, since: '0.4.0' },
        sequence: { components: true, since: '0.4.0' },
        if: { args: [{ _: 'test' }, { _: 'consequent' }, { _: 'alternate', optional: true }], since: '0.4.0' },
        if_nosave: { args: [{ _: 'test' }, { _: 'consequent' }, { _: 'alternate', optional: true }], since: '0.4.0' },
        while: { args: [{ _: 'test' }, { _: 'body' }], since: '0.4.0' },
        while_nosave: { args: [{ _: 'test' }, { _: 'body' }], since: '0.4.0' },
        dowhile: { args: [{ _: 'body' }, { _: 'test' }], since: '0.4.0' },
        dowhile_nosave: { args: [{ _: 'body' }, { _: 'test' }], since: '0.4.0' },
        try: { args: [{ _: 'body' }, { _: 'handler' }], since: '0.4.0' },
        finally: { args: [{ _: 'body' }, { _: 'finalizer' }], since: '0.4.0' },
        retain: { components: true, since: '0.4.0' },
        retain_catch: { components: true, since: '0.4.0' },
        let: { args: [{ _: 'declarations', type: 'object' }], components: true, since: '0.4.0' },
        mask: { components: true, since: '0.4.0' },
        action: { args: [{ _: 'name', type: 'string' }, { _: 'action', type: 'object', optional: true }], since: '0.4.0' },
        composition: { args: [{ _: 'name', type: 'string' }, { _: 'composition' }], since: '0.4.0' },
        repeat: { args: [{ _: 'count', type: 'number' }], components: true, since: '0.4.0' },
        retry: { args: [{ _: 'count', type: 'number' }], components: true, since: '0.4.0' },
        value: { args: [{ _: 'value', type: 'value' }], since: '0.4.0' },
        literal: { args: [{ _: 'value', type: 'value' }], since: '0.4.0' },
        function: { args: [{ _: 'function', type: 'object' }], since: '0.4.0' }
    }

    // composer error class
    class ComposerError extends Error {
        constructor(message, argument) {
            super(message + (argument !== undefined ? '\\nArgument: ' + util.inspect(argument) : ''))
        }
    }

    // composition class
    class Composition {
        // weaker instanceof to tolerate multiple instances of this class
        static [Symbol.hasInstance](instance) {
            return instance.constructor && instance.constructor.name === Composition.name
        }

        // construct a composition object with the specified fields
        constructor(composition) {
            return Object.assign(this, composition)
        }

        // apply f to all fields of type composition
        visit(f) {
            const combinator = combinators[this.type]
            if (combinator.components) {
                this.components = this.components.map(f)
            }
            for (let arg of combinator.args || []) {
                if (arg.type === undefined) {
                    this[arg._] = f(this[arg._], arg._)
                }
            }
        }
    }

    // compiler class
    class Compiler {
        // detect task type and create corresponding composition object
        task(task) {
            if (arguments.length > 1) throw new ComposerError('Too many arguments')
            if (task === null) return this.empty()
            if (task instanceof Composition) return task
            if (typeof task === 'function') return this.function(task)
            if (typeof task === 'string') return this.action(task)
            throw new ComposerError('Invalid argument', task)
        }

        // function combinator: stringify function code
        function(fun) {
            if (arguments.length > 1) throw new ComposerError('Too many arguments')
            if (typeof fun === 'function') {
                fun = `${fun}`
                if (fun.indexOf('[native code]') !== -1) throw new ComposerError('Cannot capture native function', fun)
            }
            if (typeof fun === 'string') {
                fun = { kind: 'nodejs:default', code: fun }
            }
            if (typeof fun !== 'object' || fun === null) throw new ComposerError('Invalid argument', fun)
            return new Composition({ type: 'function', function: { exec: fun } })
        }

        // lowering

        _empty() {
            return this.sequence()
        }

        _seq(composition) {
            return this.sequence(...composition.components)
        }

        _value(composition) {
            return this._literal(composition)
        }

        _literal(composition) {
            return this.let({ value: composition.value }, () => value)
        }

        _retain(composition) {
            return this.let(
                { params: null },
                args => { params = args },
                this.mask(...composition.components),
                result => ({ params, result }))
        }

        _retain_catch(composition) {
            return this.seq(
                this.retain(
                    this.finally(
                        this.seq(...composition.components),
                        result => ({ result }))),
                ({ params, result }) => ({ params, result: result.result }))
        }

        _if(composition) {
            return this.let(
                { params: null },
                args => { params = args },
                this.if_nosave(
                    this.mask(composition.test),
                    this.seq(() => params, this.mask(composition.consequent)),
                    this.seq(() => params, this.mask(composition.alternate))))
        }

        _while(composition) {
            return this.let(
                { params: null },
                args => { params = args },
                this.while_nosave(
                    this.mask(composition.test),
                    this.seq(() => params, this.mask(composition.body), args => { params = args })),
                () => params)
        }

        _dowhile(composition) {
            return this.let(
                { params: null },
                args => { params = args },
                this.dowhile_nosave(
                    this.seq(() => params, this.mask(composition.body), args => { params = args }),
                    this.mask(composition.test)),
                () => params)
        }

        _repeat(composition) {
            return this.let(
                { count: composition.count },
                this.while(
                    () => count-- > 0,
                    this.mask(this.seq(...composition.components))))
        }

        _retry(composition) {
            return this.let(
                { count: composition.count },
                params => ({ params }),
                this.dowhile(
                    this.finally(({ params }) => params, this.mask(this.retain_catch(...composition.components))),
                    ({ result }) => result.error !== undefined && count-- > 0),
                ({ result }) => result)
        }

        // define combinator methods for the standard combinators
        static init() {
            for (let type in combinators) {
                const combinator = combinators[type]
                // do not overwrite hand-written combinators
                Compiler.prototype[type] = Compiler.prototype[type] || function () {
                    const composition = new Composition({ type })
                    const skip = combinator.args && combinator.args.length || 0
                    if (!combinator.components && (arguments.length > skip)) {
                        throw new ComposerError('Too many arguments')
                    }
                    for (let i = 0; i < skip; ++i) {
                        const arg = combinator.args[i]
                        const argument = arg.optional ? arguments[i] || null : arguments[i]
                        switch (arg.type) {
                            case undefined:
                                composition[arg._] = this.task(argument)
                                continue
                            case 'value':
                                if (typeof argument === 'function') throw new ComposerError('Invalid argument', argument)
                                composition[arg._] = argument === undefined ? {} : argument
                                continue
                            case 'object':
                                if (argument === null || Array.isArray(argument)) throw new ComposerError('Invalid argument', argument)
                            default:
                                if (typeof argument !== arg.type) throw new ComposerError('Invalid argument', argument)
                                composition[arg._] = argument
                        }
                    }
                    if (combinator.components) {
                        composition.components = Array.prototype.slice.call(arguments, skip).map(obj => this.task(obj))
                    }
                    return composition
                }
            }
        }

        // return combinator list
        get combinators() {
            return combinators
        }

        // recursively deserialize composition
        deserialize(composition) {
            if (arguments.length > 1) throw new ComposerError('Too many arguments')
            composition = new Composition(composition) // copy
            composition.visit(composition => this.deserialize(composition))
            return composition
        }

        // label combinators with the json path
        label(composition) {
            if (arguments.length > 1) throw new ComposerError('Too many arguments')
            if (!(composition instanceof Composition)) throw new ComposerError('Invalid argument', composition)

            const label = path => (composition, name, array) => {
                composition = new Composition(composition) // copy
                composition.path = path + (name !== undefined ? (array === undefined ? `.${name}` : `[${name}]`) : '')
                // label nested combinators
                composition.visit(label(composition.path))
                return composition
            }

            return label('')(composition)
        }

        // recursively label and lower combinators to the desired set of combinators (including primitive combinators)
        lower(composition, combinators = []) {
            if (arguments.length > 2) throw new ComposerError('Too many arguments')
            if (!(composition instanceof Composition)) throw new ComposerError('Invalid argument', composition)
            if (!Array.isArray(combinators) && typeof combinators !== 'boolean' && typeof combinators !== 'string') throw new ComposerError('Invalid argument', combinators)

            if (combinators === false) return composition // no lowering
            if (combinators === true || combinators === '') combinators = [] // maximal lowering
            if (typeof combinators === 'string') { // lower to combinators of specific composer version
                combinators = Object.keys(this.combinators).filter(key => semver.gte(combinators, this.combinators[key].since))
            }

            const lower = composition => {
                composition = new Composition(composition) // copy
                // repeatedly lower root combinator
                while (combinators.indexOf(composition.type) < 0 && this[`_${composition.type}`]) {
                    const path = composition.path
                    composition = this[`_${composition.type}`](composition)
                    if (path !== undefined) composition.path = path
                }
                // lower nested combinators
                composition.visit(lower)
                return composition
            }

            return lower(composition)
        }
    }

    Compiler.init()

    return { ComposerError, Composition, Compiler }
}
'''