func lookupFunction()

in Sources/LLBNinja/NinjaBuild.swift [94:166]


    func lookupFunction(forKey rawKey: LLBKey, _ ctx: Context) -> LLBFuture<LLBFunction> {
        guard let key = rawKey as? String else {
            return ctx.group.next().makeFailedFuture(
                NinjaEngineDelegateError.unexpectedKeyType(String(describing: type(of: rawKey)))
            )
        }

        guard let code = key.first else {
            return ctx.group.next().makeFailedFuture(NinjaEngineDelegateError.invalidKey(key))
        }

        switch code {
            // A top-level target build request (expected to always be a valid target).
        case "T":
            // Must be a target.
            let target = String(key.dropFirst(1))
            guard let i = self.commandMap[target] else {
                return ctx.group.next().makeFailedFuture(NinjaEngineDelegateError.commandNotFound(target))
            }

            return ctx.group.next().makeSucceededFuture(
                LLBSimpleFunction { (fi, key, ctx) in
                    return fi.request("C" + String(i), ctx)
                }
            )

            // A build node.
        case "N":
            // If this is a command output, build the command (note that there
            // must be a level of indirection here, because the same command may
            // produce multiple outputs).
            let path = String(key.dropFirst(1))
            if let i = self.commandMap[path] {
                return ctx.group.next().makeSucceededFuture(
                    LLBSimpleFunction { (fi, key, ctx) in
                        return fi.request("C" + String(i), ctx)
                    }
                )
            }

            // Otherwise, it is an input file.
            return ctx.group.next().makeSucceededFuture(
                LLBSimpleFunction { (fi, key, ctx) in
                    return self.delegate.build(group: ctx.group, path: path).map { $0 as LLBValue }
                }
            )

            // A build command.
        case "C":
            let commandIndexStr = String(key.dropFirst(1))
            guard let i = Int(commandIndexStr) else {
                return ctx.group.next().makeFailedFuture(NinjaEngineDelegateError.unexpectedCommandKey(key))
            }

            return ctx.group.next().makeSucceededFuture(
                LLBSimpleFunction { (fi, key, ctx) in
                    // Get the command.
                    let command = self.manifest.statements[i]
                    // FIXME: For now, we just merge all the inputs. This isn't
                    // really in keeping with the Ninja semantics, but is strong.
                    var inputs = command.explicitInputs.map{ fi.request("N" + $0, ctx).asNinjaValue() }
                    inputs += command.implicitInputs.map{ fi.request("N" + $0, ctx).asNinjaValue() }
                    inputs += command.orderOnlyInputs.map{ fi.request("N" + $0, ctx).asNinjaValue() }
                    return LLBFuture.whenAllSucceed(inputs, on: ctx.group.next()).flatMap { inputs in
                        return self.delegate.build(group: ctx.group.next(), command: command, inputs: inputs).map { $0 as LLBValue }
                    }
                }
            )

        default:
            return ctx.group.next().makeFailedFuture(NinjaEngineDelegateError.unexpectedKey(key))
        }
    }