fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <sstream>
  4. #include <map>
  5. #include <vector>
  6. #include <limits>
  7. #include <memory>
  8. #include <cmath>
  9.  
  10. class BaseBody;
  11. typedef std::shared_ptr<BaseBody> BodyPtr;
  12.  
  13. class Object {
  14. public:
  15. Object(int);
  16. Object(double);
  17. Object(const std::string&);
  18. Object(const char*);
  19. Object(char);
  20. Object(bool);
  21. template<typename R, typename... T> Object(R(*)(T...));
  22. template<typename R, typename... T> Object(std::function<R(T...)>);
  23. Object();
  24. Object(BaseBody*);
  25. Object(BodyPtr);
  26. Object(const Object&);
  27.  
  28. ~Object();
  29.  
  30. Object& operator = (const Object& o);
  31. Object toString() const;
  32. Object& operator [] (const Object& key);
  33. const Object& operator [] (const Object& key) const;
  34.  
  35. Object operator ! () const;
  36. Object operator ~ () const;
  37. Object operator + () const;
  38. Object operator - () const;
  39.  
  40. friend Object operator + (const Object&, const Object&);
  41. friend Object operator - (const Object&, const Object&);
  42. friend Object operator * (const Object&, const Object&);
  43. friend Object operator / (const Object&, const Object&);
  44. friend Object operator << (const Object&, const Object&);
  45. friend Object operator >> (const Object&, const Object&);
  46. friend Object operator && (const Object&, const Object&);
  47. friend Object operator || (const Object&, const Object&);
  48. friend Object operator & (const Object&, const Object&);
  49. friend Object operator | (const Object&, const Object&);
  50. friend Object operator ^ (const Object&, const Object&);
  51.  
  52. Object& operator ++ () {
  53. return *this = *this + 1;
  54. }
  55.  
  56. Object operator ++ (int) {
  57. Object o = *this;
  58. *this = *this + 1;
  59. return o;
  60. }
  61.  
  62. Object& operator -- () {
  63. return *this = *this - 1;
  64. }
  65.  
  66. Object operator -- (int) {
  67. Object o = *this;
  68. *this = *this - 1;
  69. return o;
  70. }
  71.  
  72. private:
  73. template <typename... T>
  74. Object call (std::vector<BodyPtr>& arguments, const Object& h, T... t) const;
  75.  
  76. Object call (std::vector<BodyPtr>& arguments) const;
  77.  
  78. public:
  79. template <typename... T>
  80. Object operator () (T... t) const {
  81. std::vector<BodyPtr> v;
  82. return call(v, t...);
  83. }
  84.  
  85. Object operator () () const {
  86. std::vector<BodyPtr> v;
  87. return call(v);
  88. }
  89.  
  90. Object& operator += (const Object& rhs) { return *this = *this + rhs; }
  91. Object& operator -= (const Object& rhs) { return *this = *this - rhs; }
  92. Object& operator *= (const Object& rhs) { return *this = *this * rhs; }
  93. Object& operator /= (const Object& rhs) { return *this = *this / rhs; }
  94. Object& operator <<= (const Object& rhs) { return *this = *this << rhs; }
  95. Object& operator >>= (const Object& rhs) { return *this = *this >> rhs; }
  96. Object& operator &= (const Object& rhs) { return *this = *this & rhs; }
  97. Object& operator |= (const Object& rhs) { return *this = *this | rhs; }
  98. Object& operator ^= (const Object& rhs) { return *this = *this ^ rhs; }
  99.  
  100. friend std::ostream& operator << (std::ostream& os, const Object& o);
  101.  
  102. friend class Number;
  103. friend class String;
  104. friend class Boolean;
  105. friend class Math;
  106.  
  107. private:
  108. std::shared_ptr<BaseBody> value;
  109. };
  110.  
  111. class ObjectBody;
  112. class NumberBody;
  113. class StringBody;
  114. class BoolBody;
  115. class NullBody;
  116. class UndefinedBody;
  117.  
  118. class BaseBody {
  119. public:
  120. BaseBody() : proto(new std::map<std::string, Object>) {}
  121. BaseBody(const BaseBody& o) : proto(o.proto) {}
  122.  
  123. virtual ~BaseBody(){}
  124.  
  125. virtual BaseBody* clone () const = 0;
  126.  
  127. virtual Object rAdd (const BaseBody& lhs) const = 0;
  128. virtual Object add (const ObjectBody& rhs) const = 0;
  129. virtual Object add (const NumberBody& rhs) const = 0;
  130. virtual Object add (const StringBody& rhs) const = 0;
  131. virtual Object add (const BoolBody& rhs) const = 0;
  132. virtual Object add (const NullBody& rhs) const = 0;
  133. virtual Object add (const UndefinedBody& rhs) const = 0;
  134.  
  135. virtual Object call (std::vector<BodyPtr>& arguments) const {
  136. std::cerr << "[CALLING OBJECT]";
  137. throw;
  138. }
  139.  
  140. virtual Object& operator [] (const std::string& key) {
  141. return (*proto)[key];
  142. }
  143.  
  144. virtual const Object& operator [] (const std::string& key) const {
  145. return (*proto)[key];
  146. }
  147.  
  148. virtual const std::string toString() const = 0;
  149. virtual double toNumber() const = 0;
  150. virtual int toInt() const {
  151. double d = toNumber();
  152. if (std::isnan(d)) return 0;
  153. if (d > +9.9999999999998e24) return 0;
  154. if (d < -9.9999999999998e24) return 0;
  155. return d;
  156. }
  157. virtual bool toBool() const = 0;
  158. private:
  159. std::shared_ptr<std::map<std::string, Object>> proto;
  160. };
  161.  
  162. class ObjectBody : public BaseBody {
  163. public:
  164. virtual BaseBody* clone () const {
  165. return new ObjectBody(*this);
  166. }
  167.  
  168. virtual Object rAdd (const BaseBody& lhs) const;
  169. virtual Object add (const ObjectBody& rhs) const;
  170. virtual Object add (const NumberBody& rhs) const;
  171. virtual Object add (const StringBody& rhs) const;
  172. virtual Object add (const BoolBody& rhs) const;
  173. virtual Object add (const NullBody& rhs) const;
  174. virtual Object add (const UndefinedBody& rhs) const;
  175.  
  176. virtual const std::string toString() const {
  177. return "[object Object]";
  178. }
  179. virtual double toNumber() const {
  180. return std::numeric_limits<double>::quiet_NaN();
  181. }
  182. virtual bool toBool() const {
  183. return true;
  184. }
  185. };
  186.  
  187. class NullBody : public BaseBody {
  188. public:
  189. virtual BaseBody* clone () const {
  190. return new NullBody(*this);
  191. }
  192.  
  193. virtual Object rAdd (const BaseBody& lhs) const;
  194. virtual Object add (const ObjectBody& rhs) const;
  195. virtual Object add (const NumberBody& rhs) const;
  196. virtual Object add (const StringBody& rhs) const;
  197. virtual Object add (const BoolBody& rhs) const;
  198. virtual Object add (const NullBody& rhs) const;
  199. virtual Object add (const UndefinedBody& rhs) const;
  200.  
  201. virtual const std::string toString() const {
  202. return "null";
  203. }
  204. virtual double toNumber() const {
  205. return 0;
  206. }
  207. virtual bool toBool() const {
  208. return false;
  209. }
  210. };
  211.  
  212. class UndefinedBody : public NullBody {
  213. public:
  214. virtual BaseBody* clone () const {
  215. return new UndefinedBody(*this);
  216. }
  217.  
  218. static BodyPtr instance () {
  219. static BodyPtr instance;
  220. if(instance == NULL) instance.reset(new UndefinedBody);
  221. return instance;
  222. }
  223.  
  224. virtual Object rAdd (const BaseBody& lhs) const;
  225.  
  226. virtual const std::string toString() const {
  227. return "undefined";
  228. }
  229. virtual double toNumber() const {
  230. return std::numeric_limits<double>::quiet_NaN();
  231. }
  232. virtual bool toBool() const {
  233. return false;
  234. }
  235. };
  236.  
  237. template <size_t size, size_t index, typename R, typename... T>
  238. struct FunctionCall {
  239. template <typename... A>
  240. static Object call(std::function<R(T...)> func, std::vector<BodyPtr>& arguments, const A&... v) {
  241. BodyPtr arg = index < arguments.size() ? arguments[index] : UndefinedBody::instance();
  242. return FunctionCall<size, index+1, R, T...>::call(func, arguments, v..., Object(arg));
  243. }
  244. };
  245.  
  246. template <size_t x, typename R, typename... T>
  247. struct FunctionCall <x, x, R, T...> {
  248. template <typename... A>
  249. static Object call(std::function<R(T...)> func, std::vector<BodyPtr>& arguments, const A&... v) {
  250. return Object(func(v...));
  251. }
  252. };
  253.  
  254. template <typename R, typename... T>
  255. class FunctionBody : public ObjectBody {
  256. public:
  257. FunctionBody(std::function<R(T...)> func) : value(func) {}
  258. FunctionBody(R(*func)(T...)) : value(func) {}
  259.  
  260. virtual FunctionBody* clone () const {
  261. return new FunctionBody(*this);
  262. }
  263.  
  264. virtual const std::string toString() const {
  265. return "function () { [naive code] }";
  266. }
  267.  
  268. virtual Object call (std::vector<BodyPtr>& arguments) const {
  269. return FunctionCall<sizeof... (T), 0, R, T...>::call(value, arguments);
  270. }
  271.  
  272. private:
  273. std::function<R(T...)> value;
  274. };
  275.  
  276. class NumberBody : public BaseBody {
  277. public:
  278. explicit NumberBody(double v) : value(v) {}
  279. explicit NumberBody(int v) : value(v) {}
  280.  
  281. virtual BaseBody* clone () const {
  282. return new NumberBody(*this);
  283. }
  284.  
  285. virtual Object rAdd (const BaseBody& lhs) const;
  286. virtual Object add (const ObjectBody& rhs) const;
  287. virtual Object add (const NumberBody& rhs) const;
  288. virtual Object add (const StringBody& rhs) const;
  289. virtual Object add (const BoolBody& rhs) const;
  290. virtual Object add (const NullBody& rhs) const;
  291. virtual Object add (const UndefinedBody& rhs) const;
  292.  
  293. virtual const std::string toString() const {
  294. if(std::isnan(value)) return "NaN";
  295. if(std::isinf(value)) return value < 0 ? "-Infinity" : "Infinity";
  296.  
  297. std::stringstream s;
  298. s << value;
  299. return s.str();
  300. }
  301. virtual double toNumber() const {
  302. return value;
  303. }
  304. virtual bool toBool() const {
  305. if(std::isnan(value)) return false;
  306. return value;
  307. }
  308. private:
  309. double value;
  310. };
  311.  
  312. class StringBody : public BaseBody {
  313. public:
  314. explicit StringBody(const std::string& s) : value(s) {}
  315. explicit StringBody(char c) : value() {
  316. value += c;
  317. }
  318.  
  319. virtual BaseBody* clone () const {
  320. return new StringBody(*this);
  321. }
  322.  
  323. virtual Object rAdd (const BaseBody& lhs) const;
  324. virtual Object add (const ObjectBody& rhs) const;
  325. virtual Object add (const NumberBody& rhs) const;
  326. virtual Object add (const StringBody& rhs) const;
  327. virtual Object add (const BoolBody& rhs) const;
  328. virtual Object add (const NullBody& rhs) const;
  329. virtual Object add (const UndefinedBody& rhs) const;
  330.  
  331. virtual const std::string toString() const {
  332. return value;
  333. }
  334. virtual double toNumber() const {
  335. std::stringstream s(value);
  336. double v;
  337. s >> v;
  338. return v;
  339. }
  340. virtual bool toBool() const {
  341. return value.size();
  342. }
  343. private:
  344. std::string value;
  345. };
  346.  
  347. class BoolBody : public BaseBody {
  348. public:
  349. explicit BoolBody(bool b) : value(b) {}
  350.  
  351. virtual BaseBody* clone () const {
  352. return new BoolBody(*this);
  353. }
  354.  
  355. virtual Object rAdd (const BaseBody& lhs) const;
  356. virtual Object add (const ObjectBody& rhs) const;
  357. virtual Object add (const NumberBody& rhs) const;
  358. virtual Object add (const StringBody& rhs) const;
  359. virtual Object add (const BoolBody& rhs) const;
  360. virtual Object add (const NullBody& rhs) const;
  361. virtual Object add (const UndefinedBody& rhs) const;
  362.  
  363. virtual const std::string toString() const {
  364. return value ? "true" : "false";
  365. }
  366. virtual double toNumber() const {
  367. return value;
  368. }
  369. virtual bool toBool() const {
  370. return value;
  371. }
  372. private:
  373. bool value;
  374. };
  375.  
  376. Object ObjectBody::rAdd (const BaseBody& lhs) const {
  377. return lhs.add(*this);
  378. }
  379. Object ObjectBody::add (const ObjectBody& rhs) const {
  380. return Object(toString() + rhs.toString());
  381. }
  382. Object ObjectBody::add (const NumberBody& rhs) const {
  383. return Object(toString() + rhs.toString());
  384. }
  385. Object ObjectBody::add (const StringBody& rhs) const {
  386. return Object(toString() + rhs.toString());
  387. }
  388. Object ObjectBody::add (const BoolBody& rhs) const {
  389. return Object(toString() + rhs.toString());
  390. }
  391. Object ObjectBody::add (const NullBody& rhs) const {
  392. return Object(toString() + rhs.toString());
  393. }
  394. Object ObjectBody::add (const UndefinedBody& rhs) const {
  395. return Object(toString() + rhs.toString());
  396. }
  397.  
  398. Object NumberBody::rAdd (const BaseBody& lhs) const {
  399. return lhs.add(*this);
  400. }
  401. Object NumberBody::add (const ObjectBody& rhs) const {
  402. return Object(toString() + rhs.toString());
  403. }
  404. Object NumberBody::add (const NumberBody& rhs) const {
  405. return Object(toNumber() + rhs.toNumber());
  406. }
  407. Object NumberBody::add (const StringBody& rhs) const {
  408. return Object(toString() + rhs.toString());
  409. }
  410. Object NumberBody::add (const BoolBody& rhs) const {
  411. return Object(toNumber() + rhs.toNumber());
  412. }
  413. Object NumberBody::add (const NullBody& rhs) const {
  414. return Object(toNumber() + rhs.toNumber());
  415. }
  416. Object NumberBody::add (const UndefinedBody& rhs) const {
  417. return Object(toNumber() + rhs.toNumber());
  418. }
  419.  
  420. Object StringBody::rAdd (const BaseBody& lhs) const {
  421. return lhs.add(*this);
  422. }
  423. Object StringBody::add (const ObjectBody& rhs) const {
  424. return Object(toString() + rhs.toString());
  425. }
  426. Object StringBody::add (const NumberBody& rhs) const {
  427. return Object(toString() + rhs.toString());
  428. }
  429. Object StringBody::add (const StringBody& rhs) const {
  430. return Object(toString() + rhs.toString());
  431. }
  432. Object StringBody::add (const BoolBody& rhs) const {
  433. return Object(toString() + rhs.toString());
  434. }
  435. Object StringBody::add (const NullBody& rhs) const {
  436. return Object(toString() + rhs.toString());
  437. }
  438. Object StringBody::add (const UndefinedBody& rhs) const {
  439. return Object(toString() + rhs.toString());
  440. }
  441.  
  442. Object BoolBody::rAdd (const BaseBody& lhs) const {
  443. return lhs.add(*this);
  444. }
  445. Object BoolBody::add (const ObjectBody& rhs) const {
  446. return Object(toString() + rhs.toString());
  447. }
  448. Object BoolBody::add (const NumberBody& rhs) const {
  449. return Object(toString() + rhs.toString());
  450. }
  451. Object BoolBody::add (const StringBody& rhs) const {
  452. return Object(toString() + rhs.toString());
  453. }
  454. Object BoolBody::add (const BoolBody& rhs) const {
  455. return Object(toNumber() + rhs.toNumber());
  456. }
  457. Object BoolBody::add (const NullBody& rhs) const {
  458. return Object(toNumber() + rhs.toNumber());
  459. }
  460. Object BoolBody::add (const UndefinedBody& rhs) const {
  461. return Object(toNumber() + rhs.toNumber());
  462. }
  463.  
  464. Object NullBody::rAdd (const BaseBody& lhs) const {
  465. return lhs.add(*this);
  466. }
  467. Object NullBody::add (const ObjectBody& rhs) const {
  468. return Object(toString() + rhs.toString());
  469. }
  470. Object NullBody::add (const NumberBody& rhs) const {
  471. return Object(toNumber() + rhs.toNumber());
  472. }
  473. Object NullBody::add (const StringBody& rhs) const {
  474. return Object(toString() + rhs.toString());
  475. }
  476. Object NullBody::add (const BoolBody& rhs) const {
  477. return Object(toNumber() + rhs.toNumber());
  478. }
  479. Object NullBody::add (const NullBody& rhs) const {
  480. return Object(toNumber() + rhs.toNumber());
  481. }
  482. Object NullBody::add (const UndefinedBody& rhs) const {
  483. return Object(toNumber() + rhs.toNumber());
  484. }
  485.  
  486. Object UndefinedBody::rAdd (const BaseBody& lhs) const {
  487. return lhs.add(*this);
  488. }
  489.  
  490. Object::Object(int v) : value(new NumberBody(v)) {}
  491. Object::Object(double v) : value(new NumberBody(v)) {}
  492. Object::Object(const std::string& v) : value(new StringBody(v)) {}
  493. Object::Object(const char* v) : value(new StringBody(v)) {}
  494. Object::Object(char v) : value(new StringBody(v)) {}
  495. template<typename R, typename... T>
  496. Object::Object(R(*v)(T...)) : value(new FunctionBody<R, T...>(v)) {}
  497. template<typename R, typename... T>
  498. Object::Object(std::function<R(T...)> v) : value(new FunctionBody<R, T...>(v)) {}
  499. Object::Object(bool v) : value(new BoolBody(v)) {}
  500. Object::Object() : value(new ObjectBody) {}
  501. Object::Object(BaseBody* o) : value(o) {}
  502. Object::Object(BodyPtr o) : value(o) {}
  503. Object::Object(const Object& o) : value(o.value) {}
  504. Object::~Object() { }
  505.  
  506. Object& Object::operator = (const Object& o) {
  507. if(&o == this) return *this;
  508. value = o.value;
  509. return *this;
  510. }
  511.  
  512. Object operator + (const Object& lhs, const Object& rhs) {
  513. return rhs.value->rAdd(*(lhs.value));
  514. }
  515.  
  516. Object operator - (const Object& lhs, const Object& rhs) {
  517. return Object(lhs.value->toNumber() - rhs.value->toNumber());
  518. }
  519.  
  520. Object operator * (const Object& lhs, const Object& rhs) {
  521. return Object(lhs.value->toNumber() * rhs.value->toNumber());
  522. }
  523.  
  524. Object operator / (const Object& lhs, const Object& rhs) {
  525. return Object(lhs.value->toNumber() / rhs.value->toNumber());
  526. }
  527.  
  528. Object operator << (const Object& lhs, const Object& rhs) {
  529. return Object(lhs.value->toInt() << rhs.value->toInt());
  530. }
  531. Object operator >> (const Object& lhs, const Object& rhs) {
  532. return Object(lhs.value->toInt() >> rhs.value->toInt());
  533. }
  534. Object operator && (const Object& lhs, const Object& rhs) {
  535. return lhs.value->toBool() ? rhs : lhs;
  536. }
  537. Object operator || (const Object& lhs, const Object& rhs) {
  538. return lhs.value->toBool() ? lhs : rhs;
  539. }
  540. Object operator & (const Object& lhs, const Object& rhs) {
  541. return Object(lhs.value->toInt() & rhs.value->toInt());
  542. }
  543. Object operator | (const Object& lhs, const Object& rhs) {
  544. return Object(lhs.value->toInt() | rhs.value->toInt());
  545. }
  546. Object operator ^ (const Object& lhs, const Object& rhs) {
  547. return Object(lhs.value->toInt() ^ rhs.value->toInt());
  548. }
  549.  
  550. Object Object::toString() const {
  551. return Object(value->toString());
  552. }
  553.  
  554. Object& Object::operator [] (const Object& key) {
  555. return (*value)[key.value->toString()];
  556. }
  557.  
  558. const Object& Object::operator [] (const Object& key) const {
  559. return (*value)[key.value->toString()];
  560. }
  561.  
  562. Object Object::operator ! () const {
  563. return Object(!value->toBool());
  564. }
  565.  
  566. Object Object::operator ~ () const {
  567. return Object(~value->toInt());
  568. }
  569.  
  570. Object Object::operator + () const {
  571. return Object(value->toNumber());
  572. }
  573.  
  574. Object Object::operator - () const {
  575. return Object(-value->toNumber());
  576. }
  577.  
  578. template <typename... T>
  579. Object Object::call (std::vector<BodyPtr>& arguments, const Object& h, T... t) const {
  580. arguments.push_back(h.value);
  581. return call(arguments, t...);
  582. }
  583.  
  584. Object Object::call (std::vector<BodyPtr>& arguments) const {
  585. return value->call(arguments);
  586. }
  587.  
  588. std::ostream& operator << (std::ostream& os, const Object& o) {
  589. return os << o.value->toString();
  590. }
  591.  
  592. static Object null(new NullBody);
  593. static Object undefined(new UndefinedBody);
  594. static Object NaN(std::numeric_limits<double>::quiet_NaN());
  595. static Object Infinity(std::numeric_limits<double>::infinity());
  596. static Object Number(static_cast<std::function<Object(Object)>>([](Object x) { return +x; }));
  597. static Object String(static_cast<std::function<Object(Object)>>([](Object x) { return x + ""; }));
  598. static Object Boolean(static_cast<std::function<Object(Object)>>([](Object x) { return !!x; }));
  599.  
  600. typedef Object var;
  601.  
  602. class ConsoleLogBody : public ObjectBody {
  603. virtual ConsoleLogBody* clone () const {
  604. return new ConsoleLogBody(*this);
  605. }
  606.  
  607. virtual const std::string toString() const {
  608. return "function log() { [naive code] }";
  609. }
  610.  
  611. virtual Object call (std::vector<BodyPtr>& arguments) const {
  612. for(size_t i = 0; i < arguments.size(); ++i) {
  613. if(i) std::cout << ' ';
  614. std::cout << arguments[i]->toString();
  615. }
  616. std::cout << std::endl;
  617. return undefined;
  618. }
  619. };
  620.  
  621. class Console : public Object {
  622. public:
  623. Console() : log(new ConsoleLogBody) {}
  624. Object log;
  625. } console;
  626.  
  627. struct Math : public Object {
  628. Math() :
  629. sin(static_cast<std::function<Object(Object)>>([](Object x) { return std::sin(x.value->toNumber()); })),
  630. cos(static_cast<std::function<Object(Object)>>([](Object x) { return std::cos(x.value->toNumber()); })),
  631. PI(3.1415926) {}
  632. Object sin, cos, PI;
  633. } Math;
  634.  
  635. struct Window : public Object {
  636. Window() : Math(Math), console(console) {}
  637. Object& Math, &console;
  638. } window;
  639.  
  640. // TODO: как-то переписать unary, binary на Object(lambda_t)
  641. template <typename F>
  642. Object unary(F f) {
  643. return Object(static_cast<std::function<Object(Object)>>(f));
  644. }
  645.  
  646. template <typename F>
  647. Object binary(F f) {
  648. return Object(static_cast<std::function<Object(Object, Object)>>(f));
  649. }
  650.  
  651. int main() {
  652. window["console"] = console;
  653. window["Math"] = Math;
  654. Math["sin"] = Math.sin;
  655. Math["cos"] = Math.cos;
  656. Math["PI"] = Math.PI;
  657. console["log"] = console.log;
  658.  
  659. // EXAMPLE (Church numerals):
  660.  
  661. var zero = unary([](var f){ return unary([f](var x){ return x; }); });
  662. var succ = unary([](var n){ return unary([n](var f){ return unary([n,f](var x){ return f(n(f)(x)); }); }); });
  663. var plus = unary([succ](var m){ return unary([m,succ](var n){ return m(succ)(n); }); });
  664. var mult = unary([](var m){ return unary([m](var n){ return unary([m,n](var f){ return m(n(f)); }); }); });
  665. var pred = unary([](var n){ return unary([n](var f){ return unary([n,f](var x){ return n (unary([f,x](var g){ return unary([f,g,x](var h){ return h (g (f)); }); })) (unary([x](var u){ return x; })) (unary([](var u){ return u; })); }); }); });
  666.  
  667. var inc = unary([](var x) { return x+1; });
  668. var zeroValue = 0;
  669.  
  670. console.log("0 is", zero(inc)(zeroValue));
  671. var two = succ(succ(zero));
  672. console.log("2 is", two(inc)(zeroValue));
  673. var four = plus(two)(two);
  674. console.log("4 is", four(inc)(zeroValue));
  675. var eight = mult(two)(four);
  676. console.log("8 is", eight(inc)(zeroValue));
  677. var seven = pred(eight);
  678. console.log("7 is", seven(inc)(zeroValue));
  679.  
  680. console.log("7 is", unary([](var n){return unary([n](var f){return unary([n,f](var x){return n(unary([f,x](var g){return unary([f,g,x](var h){return h(g(f));});}))(unary([x](var u){return x;}))(unary([](var u){return u;}));});});})(unary([](var m){return unary([m](var n){return unary([m,n](var f){return m(n(f));});});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](var x){return x;});}))))(unary([](var m){return unary([m](var n){return m(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});}))(n);});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](var x){return x;});}))))(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](var x){return x;});}))))))(unary([](var x){return x+1;}))(0));
  681.  
  682. // EXAMPLE (JS):
  683.  
  684. var x = 3;
  685. var y = x + null;
  686. var z = "hello, " + y;
  687. var n = NaN << NaN;
  688. var f = Object(static_cast<std::function<Object(Object, Object)>>([](Object x, Object y){ return x+y; }));
  689.  
  690. console.log("x = " + x + " y = " + y + " z = " + z);
  691. console.log("x =", x,"y =", y, "z =", z);
  692. console.log(String("222") + true);
  693. console.log(String("222") + 3);
  694. console.log(Number("222") + 3);
  695. console.log(NaN << NaN, !NaN);
  696. console.log(undefined + 1);
  697. console.log(f("hello, ", "world"));
  698. console.log("sin(pi/4) = ", Math.sin(Math.PI / 4));
  699. console["log"]("sin(pi/4) = ", window["Math"]["sin"](Math["PI"] / 4));
  700. }
Success #stdin #stdout 0s 15344KB
stdin
Standard input is empty
stdout
0 is 0
2 is 2
4 is 4
8 is 8
7 is 7
7 is 7
x = 3 y = 3 z = hello, 3
x = 3 y = 3 z = hello, 3
222true
2223
225
0 true
NaN
hello, world
sin(pi/4) =  0.707107
sin(pi/4) =  0.707107