238 lines
5.8 KiB
C++
238 lines
5.8 KiB
C++
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you 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.
|
|
*/
|
|
|
|
/* $Rev$ $Date$ */
|
|
|
|
#ifndef tuscany_function_hpp
|
|
#define tuscany_function_hpp
|
|
|
|
/**
|
|
* Lambda function type.
|
|
*/
|
|
|
|
#include <utility>
|
|
#include "fstream.hpp"
|
|
#include "gc.hpp"
|
|
#include "config.hpp"
|
|
|
|
namespace tuscany {
|
|
|
|
#ifdef WANT_MAINTAINER_COUNTERS
|
|
|
|
/**
|
|
* Debug counters.
|
|
*/
|
|
long int countProxies;
|
|
long int countFProxies = 0;
|
|
long int countCProxies = 0;
|
|
long int countLambdas = 0;
|
|
long int countELambdas = 0;
|
|
long int countCLambdas = 0;
|
|
long int countFLambdas = 0;
|
|
|
|
bool resetLambdaCounters() {
|
|
countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0;
|
|
return true;
|
|
}
|
|
|
|
bool checkLambdaCounters() {
|
|
return countLambdas == 0;
|
|
}
|
|
|
|
bool printLambdaCounters() {
|
|
cout << "countLambdas " << countLambdas << endl;
|
|
cout << "countELambdas " << countELambdas << endl;
|
|
cout << "countFLambdas " << countFLambdas << endl;
|
|
cout << "countCLambdas " << countCLambdas << endl;
|
|
cout << "countProxies " << countProxies << endl;
|
|
cout << "countFProxies " << countFProxies << endl;
|
|
cout << "countCProxies " << countCProxies << endl;
|
|
return true;
|
|
}
|
|
|
|
#else
|
|
|
|
#define resetLambdaCounters()
|
|
#define checkLambdaCounters() true
|
|
#define printLambdaCounters()
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Lambda function type.
|
|
*/
|
|
|
|
template<typename R, typename... P> class Callable {
|
|
public:
|
|
Callable() {
|
|
}
|
|
|
|
virtual const size_t size() const = 0;
|
|
|
|
virtual const R operator()(P... p) const = 0;
|
|
|
|
virtual ~Callable() {
|
|
}
|
|
|
|
template<typename F> class Proxy: public Callable {
|
|
public:
|
|
Proxy(const F& f) : function(f) {
|
|
debug_inc(countProxies);
|
|
debug_inc(countFProxies);
|
|
}
|
|
|
|
Proxy(const Proxy& p) : function(p.function) {
|
|
debug_inc(countProxies);
|
|
debug_inc(countCProxies);
|
|
}
|
|
|
|
~Proxy() {
|
|
debug_dec(countProxies);
|
|
}
|
|
|
|
virtual const R operator() (P... p) const {
|
|
return function(std::forward<P>(p)...);
|
|
}
|
|
|
|
virtual const size_t size() const {
|
|
return sizeof(function);
|
|
}
|
|
|
|
private:
|
|
const F function;
|
|
};
|
|
};
|
|
|
|
template<typename S> class lambda;
|
|
|
|
template<typename R, typename... P> class lambda<R(P...)> {
|
|
public:
|
|
lambda() : callable(0) {
|
|
debug_inc(countLambdas);
|
|
debug_inc(countELambdas);
|
|
}
|
|
|
|
template<typename F> lambda(const F f) {
|
|
debug_inc(countLambdas);
|
|
debug_inc(countFLambdas);
|
|
|
|
typedef typename CallableType::template Proxy<F> ProxyType;
|
|
callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
|
|
}
|
|
|
|
lambda(const lambda& l) {
|
|
debug_inc(countLambdas);
|
|
debug_inc(countCLambdas);
|
|
callable = l.callable;
|
|
}
|
|
|
|
const lambda& operator=(const lambda& l) {
|
|
if (this == &l)
|
|
return *this;
|
|
callable = l.callable;
|
|
return *this;
|
|
}
|
|
|
|
~lambda() {
|
|
debug_dec(countLambdas);
|
|
}
|
|
|
|
const bool operator==(const lambda& l) const {
|
|
if (this == &l)
|
|
return true;
|
|
return callable == l.callable;
|
|
}
|
|
|
|
const bool operator!=(const lambda& l) const {
|
|
return !this->operator==(l);
|
|
}
|
|
|
|
const R operator()(P... p) const {
|
|
return (*callable)(std::forward<P>(p)...);
|
|
}
|
|
|
|
template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&);
|
|
template<typename S> friend const bool isNil(const lambda<S>& l);
|
|
|
|
private:
|
|
typedef Callable<R,P...> CallableType;
|
|
gc_ptr<CallableType> callable;
|
|
};
|
|
|
|
template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) {
|
|
return out << "lambda::" << l.callable;
|
|
}
|
|
|
|
/**
|
|
* Return true if a lambda is nil.
|
|
*/
|
|
template<typename S> const bool isNil(const lambda<S>& l) {
|
|
return ((void*)l.callable) == 0;
|
|
}
|
|
|
|
/**
|
|
* Curry a lambda function.
|
|
*/
|
|
template<typename R, typename T, typename... P> class curried {
|
|
public:
|
|
curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) {
|
|
}
|
|
|
|
const R operator()(P... p) const {
|
|
return f(v, std::forward<P>(p)...);
|
|
}
|
|
|
|
private:
|
|
const T v;
|
|
const lambda<R(T, P...)>f;
|
|
};
|
|
|
|
template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) {
|
|
return curried<R, T, P...>(f, t);
|
|
}
|
|
|
|
template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) {
|
|
return curry(curry(f, t), u);
|
|
}
|
|
|
|
template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) {
|
|
return curry(curry(curry(f, t), u), v);
|
|
}
|
|
|
|
/**
|
|
* A lambda function that returns the given value.
|
|
*/
|
|
template<typename T> class returnResult {
|
|
public:
|
|
returnResult(const T& v) :
|
|
v(v) {
|
|
}
|
|
const T operator()() const {
|
|
return v;
|
|
}
|
|
private:
|
|
const T v;
|
|
};
|
|
|
|
template<typename T> const lambda<T()> result(const T& v) {
|
|
return returnResult<T> (v);
|
|
}
|
|
|
|
}
|
|
#endif /* tuscany_function_hpp */
|