From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: David Thompson Newsgroups: gmane.lisp.guile.user Subject: Potluck dish - Simple functional reactive programming Date: Sun, 16 Feb 2014 13:32:13 -0500 Message-ID: <87ob26x61e.fsf@izanagi.i-did-not-set--mail-host-address--so-tickle-me> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1392575567 12753 80.91.229.3 (16 Feb 2014 18:32:47 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 16 Feb 2014 18:32:47 +0000 (UTC) To: guile-user@gnu.org Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Sun Feb 16 19:32:53 2014 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1WF6WK-0005QF-FA for guile-user@m.gmane.org; Sun, 16 Feb 2014 19:32:52 +0100 Original-Received: from localhost ([::1]:34611 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WF6WJ-0006Fy-Qj for guile-user@m.gmane.org; Sun, 16 Feb 2014 13:32:51 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:36204) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WF6W2-0006Fp-Eh for guile-user@gnu.org; Sun, 16 Feb 2014 13:32:42 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WF6Vu-0004rI-4m for guile-user@gnu.org; Sun, 16 Feb 2014 13:32:34 -0500 Original-Received: from na3sys009aog126.obsmtp.com ([74.125.149.155]:37852) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WF6Vt-0004r4-Mz for guile-user@gnu.org; Sun, 16 Feb 2014 13:32:26 -0500 Original-Received: from mail-qa0-f48.google.com ([209.85.216.48]) (using TLSv1) by na3sys009aob126.postini.com ([74.125.148.12]) with SMTP ID DSNKUwEENx1W2W03+eEynf9lxT+TxXFD8GDP@postini.com; Sun, 16 Feb 2014 10:32:25 PST Original-Received: by mail-qa0-f48.google.com with SMTP id f11so20594199qae.7 for ; Sun, 16 Feb 2014 10:32:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:user-agent:date:message-id :mime-version:content-type; bh=X1xPHKHCNkxjjp/XSA3haex7KCQSsnlmEenOSxLBkO0=; b=KjLa5DP0r93E3FLc4NSBCk91ngojZgkcwFOn6r0zHVmxvbgNO1vSHg3oCxZx5XOUyg IghZEnOOKZPur0BFqWjRNemrzTHV4rHHw4AQdXAgMLBBD2UhwBOnhl1UDzjlhRO/d3lI zraLdMEPFwTvoKOvPTomGW9IHTmiZRRWoJv+nloMEe7DsrF9peLJYXBVt+iLYYQRt5Ia RAU6hQxy04Q/RXaAU0SYM9mhAdzTaMLwBjLLNEcv7RRxx5YPktqUIxbEdGINXfFvJbXH x9XqgXpmTtXzdZ0bTrICPRe2v4W0ipCuyJZNwFIAFWqYQOpnta8UYJmWg3UUZbssBTlI O6YA== X-Gm-Message-State: ALoCoQm6miTZJE8EXyzDO8QaKTdjoZBDoidjaZ/DJ8vsO5w4kSZw4kVYlphFB2LYHse7tVV58aYQX7auWgFWFarsAhPAIWOxgxVMBtCoqD6i7hZ6zyMlnqnPO/jnVTMuzQxD3T7bXvAON+IUFTnOvcmI9lAZbaIBSQ== X-Received: by 10.140.105.35 with SMTP id b32mr28247244qgf.36.1392575542815; Sun, 16 Feb 2014 10:32:22 -0800 (PST) X-Received: by 10.140.105.35 with SMTP id b32mr28247238qgf.36.1392575542719; Sun, 16 Feb 2014 10:32:22 -0800 (PST) Original-Received: from izanagi (209-6-40-86.c3-0.smr-ubr1.sbo-smr.ma.cable.rcn.com. [209.6.40.86]) by mx.google.com with ESMTPSA id k1sm37229097qat.16.2014.02.16.10.32.20 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 16 Feb 2014 10:32:21 -0800 (PST) User-Agent: Notmuch/0.17 (http://notmuchmail.org) Emacs/24.3.1 (x86_64-pc-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x X-Received-From: 74.125.149.155 X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:11063 Archived-At: --=-=-= Content-Type: text/plain Hello Guilers, I didn't have time to put together a proper potluck dish, but I wanted to find something to share anyway. Lately I've been playing around with functional reactive programming (FRP) applied to video games. This style of programming allows for a declarative, functional way of describing time-varying values. Contrast this method of programming with more traditional hooks and callbacks. My FRP module can be used on top of hooks to escape callback hell. And now for a simple example. This morning I was writing a program using my game engine, guile-2d, and I wanted to display the number of times the GC has been run in the game window. Without FRP I could have done something like: (define gc-label-position (vector2 0 40)) (define gc-counter 0) (define (make-gc-label) (let ((text (format #f "GCs: ~d" counter))) (make-label font text gc-label-position))) (define gc-label (make-gc-label)) (add-hook! after-gc-hook (lambda () (set! gc-counter (1+ gc-counter)) (set! gc-label (make-gc-label)))) This code isn't terrible, but wouldn't it be nice to declare that 'gc-label' will always contain a string with the number of GC runs in it instead? Enter FRP: (define gc-label-position (vector2 0 40)) (define gc-counter (make-root-signal 0)) (define gc-label (signal-map (lambda (counter) (let ((text (format #f "GCs: ~d" counter))) (make-label font text gc-label-position))) gc-counter)) (add-hook! after-gc-hook (lambda () (signal-set! gc-counter (1+ (signal-ref gc-counter))))) 'gc-counter' and 'gc-label' both become 'signals', or time-varying values. Now, when the GC runs, the 'gc-counter' signal is incremented by 1. The act of setting 'gc-counter' triggers propagation of the counter to the 'gc-label' signal which maps the counter to a new label that prints the current number of GC runs. Magic! Note that 'after-gc-hook' is still needed to bootstrap the signal graph, but once that is out of the way it's signals all the way down. This example was fairly trivial, but what if the desired chain reaction was more complicated? Writing the logic using regular callback procedures would become a nightmare. The nightmare that JavaScript programmers constantly find themselves in. And that's my potluck dish! I'm currently working on a new version of this API that will allow the signal graph to handle the dynamic environment of the REPL, but it's not ready yet. Thanks to all of the Guile maintainers and contributors for the great work these past 3 years! - David Thompson --=-=-= Content-Type: application/octet-stream Content-Disposition: inline; filename=signals.scm Content-Transfer-Encoding: base64 Ozs7IGd1aWxlLTJkCjs7OyBDb3B5cmlnaHQgKEMpIDIwMTMgRGF2aWQgVGhvbXBzb24gPGR0aG9t cHNvbjJAd29yY2VzdGVyLmVkdT4KOzs7Cjs7OyBHdWlsZS0yZCBpcyBmcmVlIHNvZnR3YXJlOiB5 b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0Cjs7OyB1bmRlciB0aGUgdGVy bXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcwo7OzsgcHVibGlz aGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2Yg dGhlCjs7OyBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgo7 OzsKOzs7IEd1aWxlLTJkIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBi ZSB1c2VmdWwsIGJ1dAo7OzsgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUg aW1wbGllZCB3YXJyYW50eSBvZgo7OzsgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEg UEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKOzs7IExlc3NlciBHZW5lcmFsIFB1Ymxp YyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCjs7Owo7OzsgWW91IHNob3VsZCBoYXZlIHJlY2Vp dmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwo7OzsgTGljZW5zZSBh bG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4gIElmIG5vdCwgc2VlCjs7OyA8aHR0cDovL3d3dy5nbnUu b3JnL2xpY2Vuc2VzLz4uCgo7OzsgQ29tbWVudGFyeToKOzsKOzsgU2ltcGxlIGZ1bmN0aW9uYWwg cmVhY3RpdmUgcHJvZ3JhbW1pbmcgQVBJLgo7Owo7OzsgQ29kZToKCihkZWZpbmUtbW9kdWxlICgy ZCBzaWduYWxzKQogICM6dXNlLW1vZHVsZSAoc3JmaSBzcmZpLTEpCiAgIzp1c2UtbW9kdWxlIChz cmZpIHNyZmktOSkKICAjOnVzZS1tb2R1bGUgKHNyZmkgc3JmaS0yNikKICAjOmV4cG9ydCAoc2ln bmFsPwogICAgICAgICAgICByb290LXNpZ25hbD8KICAgICAgICAgICAgbWFrZS1zaWduYWwKICAg ICAgICAgICAgbWFrZS1yb290LXNpZ25hbAogICAgICAgICAgICBzaWduYWwtcmVmCiAgICAgICAg ICAgIHNpZ25hbC1yZWYtbWF5YmUKICAgICAgICAgICAgc2lnbmFsLXJlY2VpdmVyCiAgICAgICAg ICAgIHNpZ25hbC1pbnB1dHMKICAgICAgICAgICAgc2lnbmFsLW91dHB1dHMKICAgICAgICAgICAg c2lnbmFsLWNvbm5lY3QhCiAgICAgICAgICAgIHNpZ25hbC1kaXNjb25uZWN0IQogICAgICAgICAg ICBzaWduYWwtY2xlYXIhCiAgICAgICAgICAgIHNpZ25hbC1zZXQhCiAgICAgICAgICAgIHNpZ25h bC1tZXJnZQogICAgICAgICAgICBzaWduYWwtY29tYmluZQogICAgICAgICAgICBzaWduYWwtZG8K ICAgICAgICAgICAgc2lnbmFsLW1hcAogICAgICAgICAgICBzaWduYWwtZm9sZAogICAgICAgICAg ICBzaWduYWwtZmlsdGVyCiAgICAgICAgICAgIHNpZ25hbC1yZWplY3QKICAgICAgICAgICAgc2ln bmFsLWNvbnN0YW50CiAgICAgICAgICAgIHNpZ25hbC1jb3VudCkpCgo7OzsKOzs7IFNpZ25hbHMK Ozs7Cgo7OyBTaWduYWxzIGFyZSB0aW1lLXZhcnlpbmcgdmFsdWVzLiBGb3IgZXhhbXBsZSwgYSBz aWduYWwgY291bGQKOzsgcmVwcmVzZW50IHRoZSBtb3VzZSBwb3NpdGlvbiBhdCB0aGUgY3VycmVu dCBwb2ludCBpbiB0aW1lLiBUaGUKOzsgc2lnbmFscyBBUEkgcHJvdmlkZXMgYW4gYWJzdHJhY3Rp b24gb3ZlciByZWd1bGFyIGV2ZW50LWJhc2VkCjs7IHByb2dyYW1taW5nLiBTdGF0ZSBtdXRhdGlv biBpcyBoaWRkZW4gYXdheSBhbmQgYSBmdW5jdGlvbmFsLAo7OyBkZWNsYXJhdGl2ZSBpbnRlcmZh Y2UgaXMgZXhwb3NlZC4KKGRlZmluZS1yZWNvcmQtdHlwZSA8c2lnbmFsPgogICglbWFrZS1zaWdu YWwgdmFsdWUgcHJvYyBpbnB1dHMgb3V0cHV0cykKICBzaWduYWw/CiAgKHZhbHVlIHNpZ25hbC1y ZWYgJXNpZ25hbC1zZXQhKQogIChwcm9jIHNpZ25hbC1wcm9jKQogIChpbnB1dHMgc2lnbmFsLWlu cHV0cyBzZXQtc2lnbmFsLWlucHV0cyEpCiAgKG91dHB1dHMgc2lnbmFsLW91dHB1dHMgc2V0LXNp Z25hbC1vdXRwdXRzISkpCgooZGVmaW5lIChtYWtlLXNpZ25hbCBpbml0IHByb2MgaW5wdXRzKQog ICJDcmVhdGUgYSBuZXcgc2lnbmFsIHdpdGggaW5pdGlhbCB2YWx1ZSBJTklULCBhIHByb2NlZHVy ZSBQUk9DCnRvIHRyYW5zZm9ybSBpbmNvbWluZyBzaWduYWwgdmFsdWVzIGFuZCBvbmUgb3IgbW9y ZSBzaWduYWxzIHRvIGNvbm5lY3QKdG8uIgogIChsZXQgKChzaWduYWwgKCVtYWtlLXNpZ25hbCBp bml0IHByb2MgaW5wdXRzICcoKSkpKQogICAgKGZvci1lYWNoIChjdXQgc2lnbmFsLWNvbm5lY3Qh IDw+IHNpZ25hbCkgaW5wdXRzKQogICAgc2lnbmFsKSkKCihkZWZpbmUgKG1ha2Utcm9vdC1zaWdu YWwgaW5pdCkKICAiQ3JlYXRlIGEgbmV3IHJvb3QgbGV2ZWwgc2lnbmFsIHdpdGggaW5pdGlhbCB2 YWx1ZSBJTklULiIKICAoJW1ha2Utc2lnbmFsIGluaXQgI2YgJygpICcoKSkpCgooZGVmaW5lIChy b290LXNpZ25hbD8gc2lnbmFsKQogICJSZXR1cm5zIHRydWUgaWYgYSBzaWduYWwgaGFzIG5vIHJl Y2VpdmVyIHByb2NlZHVyZSBvciBmYWxzZQpvdGhlcndpc2UuIgogIChub3QgKHNpZ25hbC1wcm9j IHNpZ25hbCkpKQoKKGRlZmluZSAoc2lnbmFsLXJlZi1tYXliZSBvYmplY3QpCiAgIlJldHJpZXZl cyB0aGUgc2lnbmFsIHZhbHVlIGZyb20gT0JKRUNUIGlmIGl0IGlzIGEgc2lnbmFsIGFuZCBvcgpz aW1wbHkgcmV0dXJucyBPQkpFQ1Qgb3RoZXJ3aXNlLiIKICAoaWYgKHNpZ25hbD8gb2JqZWN0KQog ICAgICAoc2lnbmFsLXJlZiBvYmplY3QpCiAgICAgIG9iamVjdCkpCgooZGVmaW5lIChzaWduYWwt Y29ubmVjdCEgc2lnbmFsLWluIHNpZ25hbC1vdXQpCiAgIkF0dGFjaCBTSUdOQUwtT1VUIHRvIFNJ R05BTC1JTi4gV2hlbiB0aGUgdmFsdWUgb2YgU0lHTkFMLUlOCmNoYW5nZXMsIHRoZSB2YWx1ZSB3 aWxsIGJlIHByb3BhZ2F0ZWQgdG8gU0lHTkFMLU9VVC4iCiAgKGlmIChyb290LXNpZ25hbD8gc2ln bmFsLW91dCkKICAgICAgKGVycm9yICdyb290LXNpZ25hbC1lcnJvcgogICAgICAgICAgICAgIkNh bm5vdCBjb25uZWN0IHRvIGEgcm9vdCBzaWduYWwiCiAgICAgICAgICAgICBzaWduYWwtb3V0KQog ICAgICAobGV0ICgob3V0cHV0cyAoc2lnbmFsLW91dHB1dHMgc2lnbmFsLWluKSkpCiAgICAgICAg KHNldC1zaWduYWwtb3V0cHV0cyEgc2lnbmFsLWluICAoY29ucyBzaWduYWwtb3V0IG91dHB1dHMp KSkpKQoKKGRlZmluZSAoc2lnbmFsLWRpc2Nvbm5lY3QhIHNpZ25hbC1pbiBzaWduYWwtb3V0KQog ICJEZXRhY2ggU0lHTkFMLU9VVCBmcm9tIFNJR05BTC1JTi4iCiAgKGxldCAoKGlucHV0cyAoc2ln bmFsLWlucHV0cyBzaWduYWwtb3V0KSkKICAgICAgICAob3V0cHV0cyAoc2lnbmFsLW91dHB1dHMg c2lnbmFsLWluKSkpCiAgICAoc2V0LXNpZ25hbC1pbnB1dHMhICBzaWduYWwtb3V0IChkZWxldGUg c2lnbmFsLWluICBpbnB1dHMgIGVxPykpCiAgICAoc2V0LXNpZ25hbC1vdXRwdXRzISBzaWduYWwt aW4gIChkZWxldGUgc2lnbmFsLW91dCBvdXRwdXRzIGVxPykpCiAgICA7OyBEaXNjb25uZWN0IGFs bCBpbnB1dHMgd2hlbiB0aGUgaW5wdXQgc2lnbmFsIGhhcyBubyByZW1haW5pbmcKICAgIDs7IG91 dHB1dHMgaW4gb3JkZXIgdG8gcHJldmVudCBtZW1vcnkgbGVha3MgYW5kIHVubmVjZXNzYXJ5CiAg ICA7OyBjb21wdXRhdGlvbi4KICAgICh3aGVuIChudWxsPyAoc2lnbmFsLW91dHB1dHMgc2lnbmFs LWluKSkKICAgICAgKHNpZ25hbC1jbGVhci1pbnB1dHMhIHNpZ25hbC1pbikpKSkKCihkZWZpbmUg KHNpZ25hbC1jbGVhci1vdXRwdXRzISBzaWduYWwpCiAgIkRpc2Nvbm5lY3QgYWxsIG91dHB1dCBz aWduYWxzIGZyb20gU0lHTkFMLiIKICAoZm9yLWVhY2ggKGN1dCBzaWduYWwtZGlzY29ubmVjdCEg c2lnbmFsIDw+KQogICAgICAgICAgICAoc2lnbmFsLW91dHB1dHMgc2lnbmFsKSkKICAoc2V0LXNp Z25hbC1vdXRwdXRzISBzaWduYWwgJygpKSkKCihkZWZpbmUgKHNpZ25hbC1jbGVhci1pbnB1dHMh IHNpZ25hbCkKICAiRGlzY29ubmVjdCBhbGwgaW5wdXRzIHNpZ25hbHMgZnJvbSBTSUdOQUwuIgog IChmb3ItZWFjaCAoY3V0IHNpZ25hbC1kaXNjb25uZWN0ISA8PiBzaWduYWwpCiAgICAgICAgICAg IChzaWduYWwtaW5wdXRzIHNpZ25hbCkpCiAgKHNldC1zaWduYWwtaW5wdXRzISBzaWduYWwgJygp KSkKCihkZWZpbmUgKHNpZ25hbC11cGRhdGUhIHNpZ25hbCBmcm9tKQogICJSZS1ldmFsdWF0ZSB0 aGUgc2lnbmFsIHByb2NlZHVyZSBmb3IgdGhlIHNpZ25hbCBTSUdOQUwgYXMgb3JkZXJlZApieSB0 aGUgc2lnbmFsIEZST00uIgogICgoc2lnbmFsLXByb2Mgc2lnbmFsKSBzaWduYWwgZnJvbSkpCgoo ZGVmaW5lIChzaWduYWwtcHJvcGFnYXRlISBzaWduYWwpCiAgIk5vdGlmeSBhbGwgb3V0cHV0IHNp Z25hbHMgYWJvdXQgdGhlIGN1cnJlbnQgdmFsdWUgb2YgU0lHTkFMLiIKICAoZm9yLWVhY2ggKGN1 dCBzaWduYWwtdXBkYXRlISA8PiBzaWduYWwpCiAgICAgICAgICAgIChzaWduYWwtb3V0cHV0cyBz aWduYWwpKSkKCihkZWZpbmUgKHNpZ25hbC1zZXQhIHNpZ25hbCB2YWx1ZSkKICAiQ2hhbmdlIHRo ZSBjdXJyZW50IHZhbHVlIG9mIFNJR05BTCB0byBWQUxVRSBhbmQgcHJvcGFnYXRlIFNJR05BTCB0 bwphbGwgY29ubmVjdGVkIHNpZ25hbHMuIgogICglc2lnbmFsLXNldCEgc2lnbmFsIHZhbHVlKQog IChzaWduYWwtcHJvcGFnYXRlISBzaWduYWwpKQoKKGRlZmluZSAoc3BsaWNlLXNpZ25hbHMhIG9s ZCBuZXcpCiAgIlJlbW92ZSB0aGUgaW5wdXRzIGFuZCBvdXRwdXRzIGZyb20gdGhlIHNpZ25hbCBP TEQsIGNvbm5lY3QgdGhlCm91dHB1dHMgdG8gdGhlIHNpZ25hbCBORVcsIGFuZCByZXR1cm4gTkVX LiIKICAod2hlbiAoc2lnbmFsPyBvbGQpCiAgICAobGV0ICgob3V0cHV0cyAoc2lnbmFsLW91dHB1 dHMgb2xkKSkpCiAgICAgIChzaWduYWwtY2xlYXItaW5wdXRzISBvbGQpCiAgICAgIChzaWduYWwt Y2xlYXItb3V0cHV0cyEgb2xkKQogICAgICAoZm9yLWVhY2ggKGN1dCBzaWduYWwtY29ubmVjdCEg bmV3IDw+KSBvdXRwdXRzKSkKICAgIChzaWduYWwtcHJvcGFnYXRlISBuZXcpKQogIG5ldykKCihk ZWZpbmUtc3ludGF4IGRlZmluZS1zaWduYWwKICAobGFtYmRhICh4KQogICAgKHN5bnRheC1jYXNl IHggKCkKICAgICAgOzsgU3BsaWNlIGluIG5ldyBzaWduYWwgaWYgYSBzaWduYWwgd2l0aCB0aGlz IG5hbWUgYWxyZWFkeQogICAgICA7OyBleGlzdHMuCiAgICAgICgoXyBuYW1lIChzaWduYWwgLi4u KSkKICAgICAgIChkZWZpbmVkPyAoc3ludGF4LT5kYXR1bSAjJ25hbWUpKQogICAgICAgIycoZGVm aW5lIG5hbWUgKHNwbGljZS1zaWduYWxzISBuYW1lIChzaWduYWwgLi4uKSkpKQogICAgICAoKF8g bmFtZSAoc2lnbmFsIC4uLikpCiAgICAgICAjJyhkZWZpbmUgbmFtZSAoc2lnbmFsIC4uLikpKSkp KQoKOzs7Cjs7OyBIaWdoZXIgT3JkZXIgU2lnbmFscwo7OzsKCihkZWZpbmUgKHNpZ25hbC1tZXJn ZSBzaWduYWwxIHNpZ25hbDIgLiByZXN0KQogICJDcmVhdGUgYSBuZXcgc2lnbmFsIHdob3NlIHZh bHVlIGlzIHRoZSB0aGF0IG9mIHRoZSBtb3N0IHJlY2VudGx5CmNoYW5nZWQgc2lnbmFsIGluIFNJ R05BTHMuICBUaGUgaW5pdGlhbCB2YWx1ZSBpcyB0aGF0IG9mIHRoZSBmaXJzdApzaWduYWwgaW4g U0lHTkFMUy4iCiAgKGxldCAoKHNpZ25hbHMgKGFwcGVuZCAobGlzdCBzaWduYWwxIHNpZ25hbDIp IHJlc3QpKSkKICAgIChtYWtlLXNpZ25hbCAoc2lnbmFsLXJlZiAoY2FyIHNpZ25hbHMpKQogICAg ICAgICAgICAgICAgIChsYW1iZGEgKHNlbGYgZnJvbSkKICAgICAgICAgICAgICAgICAgIChzaWdu YWwtc2V0ISBzZWxmIChzaWduYWwtcmVmIGZyb20pKSkKICAgICAgICAgICAgICAgICBzaWduYWxz KSkpCgooZGVmaW5lIChzaWduYWwtY29tYmluZSAuIHNpZ25hbHMpCiAgIkNyZWF0ZSBhIG5ldyBz aWduYWwgd2hvc2UgdmFsdWUgaXMgYSBsaXN0IG9mIHRoZSB2YWx1ZXMgc3RvcmVkIGluCnRoZSBn aXZlbiBzaWduYWxzLiIKICAoZGVmaW5lICh1cGRhdGUgc2lnbmFscykKICAgIChtYXAgc2lnbmFs LXJlZiBzaWduYWxzKSkKCiAgKG1ha2Utc2lnbmFsICh1cGRhdGUgc2lnbmFscykKICAgICAgICAg ICAgICAgKGxhbWJkYSAoc2VsZiBmcm9tKQogICAgICAgICAgICAgICAgIChzaWduYWwtc2V0ISBz ZWxmICh1cGRhdGUgKHNpZ25hbC1pbnB1dHMgc2VsZikpKSkKICAgICAgICAgICAgICAgc2lnbmFs cykpCgooZGVmaW5lIChzaWduYWwtbWFwIHByb2Mgc2lnbmFsIC4gc2lnbmFscykKICAiQ3JlYXRl IGEgbmV3IHNpZ25hbCB0aGF0IGFwcGxpZXMgUFJPQyB0byB0aGUgdmFsdWVzIHN0b3JlZCBpbiBv bmUKb3IgbW9yZSBTSUdOQUxTLiIKICAoZGVmaW5lICh1cGRhdGUgc2lnbmFscykKICAgIChhcHBs eSBwcm9jIChtYXAgc2lnbmFsLXJlZiBzaWduYWxzKSkpCgogIChsZXQgKChzaWduYWxzIChjb25z IHNpZ25hbCBzaWduYWxzKSkpCiAgICAobWFrZS1zaWduYWwgKHVwZGF0ZSBzaWduYWxzKQogICAg ICAgICAgICAgICAgIChsYW1iZGEgKHNlbGYgZnJvbSkKICAgICAgICAgICAgICAgICAgIChzaWdu YWwtc2V0ISBzZWxmICh1cGRhdGUgKHNpZ25hbC1pbnB1dHMgc2VsZikpKSkKICAgICAgICAgICAg ICAgICBzaWduYWxzKSkpCgooZGVmaW5lIChzaWduYWwtZm9sZCBwcm9jIGluaXQgc2lnbmFsKQog ICJDcmVhdGUgYSBuZXcgc2lnbmFsIHRoYXQgYXBwbGllcyBQUk9DIHRvIHRoZSB2YWx1ZXMgc3Rv cmVkIGluClNJR05BTC4gUFJPQyBpcyBhcHBsaWVkIHdpdGggdGhlIGN1cnJlbnQgdmFsdWUgb2Yg U0lHTkFMIGFuZCB0aGUKcHJldmlvdXNseSBjb21wdXRlZCB2YWx1ZSwgb3IgSU5JVCBmb3IgdGhl IGZpcnN0IGNhbGwuIgogIChtYWtlLXNpZ25hbCBpbml0CiAgICAgICAgICAgICAgIChsZXQgKChw cmV2aW91cyBpbml0KSkKICAgICAgICAgICAgICAgICAobGFtYmRhIChzZWxmIGZyb20pCiAgICAg ICAgICAgICAgICAgICAobGV0ICgodmFsdWUgKHByb2MgKHNpZ25hbC1yZWYgZnJvbSkgcHJldmlv dXMpKSkKICAgICAgICAgICAgICAgICAgICAgKHNldCEgcHJldmlvdXMgdmFsdWUpCiAgICAgICAg ICAgICAgICAgICAgIChzaWduYWwtc2V0ISBzZWxmIHZhbHVlKSkpKQogICAgICAgICAgICAgICAo bGlzdCBzaWduYWwpKSkKCihkZWZpbmUgKHNpZ25hbC1maWx0ZXIgcHJlZGljYXRlIGRlZmF1bHQg c2lnbmFsKQogICJDcmVhdGUgYSBuZXcgc2lnbmFsIHRoYXQga2VlcHMgYW4gaW5jb21pbmcgdmFs dWUgZnJvbSBTSUdOQUwgd2hlbgppdCBzYXRpZmllcyB0aGUgcHJvY2VkdXJlIFBSRURJQ0FURS4g IFRoZSB2YWx1ZSBvZiB0aGUgc2lnbmFsIGlzCkRFRkFVTFQgd2hlbiB0aGUgcHJlZGljYXRlIGlz IG5ldmVyIHNhdGlzZmllZC4iCiAgKG1ha2Utc2lnbmFsIChpZiAocHJlZGljYXRlIChzaWduYWwt cmVmIHNpZ25hbCkpCiAgICAgICAgICAgICAgICAgICAoc2lnbmFsLXJlZiBzaWduYWwpCiAgICAg ICAgICAgICAgICAgICBkZWZhdWx0KQogICAgICAgICAgICAgICAobGFtYmRhIChzZWxmIHNpZ25h bCkKICAgICAgICAgICAgICAgICAod2hlbiAocHJlZGljYXRlIChzaWduYWwtcmVmIHNpZ25hbCkp CiAgICAgICAgICAgICAgICAgICAoc2lnbmFsLXNldCEgc2VsZiAoc2lnbmFsLXJlZiBzaWduYWwp KSkpCiAgICAgICAgICAgICAgIChsaXN0IHNpZ25hbCkpKQoKKGRlZmluZSAoc2lnbmFsLXJlamVj dCBwcmVkaWNhdGUgZGVmYXVsdCBzaWduYWwpCiAgIkNyZWF0ZSBhIG5ldyBzaWduYWwgdGhhdCBk b2VzIG5vdCBrZWVwIGFuIGluY29taW5nIHZhbHVlIGZyb20KU0lHTkFMIHdoZW4gaXQgc2F0aXNm aWVzIHRoZSBwcm9jZWR1cmUgUFJFRElDQVRFLiAgVGhlIHZhbHVlIG9mIHRoZQpzaWduYWwgaXMg REVGQVVMVCB3aGVuIHRoZSBwcmVkaWNhdGUgaXMgbmV2ZXIgc2F0aXNmaWVkLiIKICAoc2lnbmFs LWZpbHRlciAobGFtYmRhICh4KSAobm90IChwcmVkaWNhdGUgeCkpKSBkZWZhdWx0IHNpZ25hbCkp CgooZGVmaW5lIChzaWduYWwtY29uc3RhbnQgY29uc3RhbnQgc2lnbmFsKQogICJDcmVhdGUgYSBu ZXcgc2lnbmFsIHdob3NlIHZhbHVlIGlzIGFsd2F5cyBDT05TVEFOVCByZWdhcmRsZXNzIG9mCndo YXQgdGhlIHZhbHVlIHJlY2VpdmVkIGZyb20gU0lHTkFMLiIKICAoc2lnbmFsLW1hcCAobGFtYmRh ICh2YWx1ZSkgY29uc3RhbnQpIHNpZ25hbCkpCgooZGVmaW5lIChzaWduYWwtY291bnQgc2lnbmFs KQogICJDcmVhdGUgYSBuZXcgc2lnbmFsIHRoYXQgaW5jcmVtZW50cyBhIGNvdW50ZXIgZXZlcnkg dGltZSBhIG5ldwp2YWx1ZSBmcm9tIFNJR05BTCBpcyByZWNlaXZlZC4iCiAgKHNpZ25hbC1mb2xk ICsgMCAoc2lnbmFsLWNvbnN0YW50IDEgc2lnbmFsKSkpCgooZGVmaW5lIChzaWduYWwtZG8gcHJv YyBzaWduYWwpCiAgIkNyZWF0ZSBhIG5ldyBzaWduYWwgdGhhdCBhcHBsaWVzIFBST0Mgd2hlbiBh IG5ldyB2YWx1ZXMgaXMgcmVjZWl2ZWQKZnJvbSBTSUdOQUwuICBUaGUgdmFsdWUgb2YgdGhlIG5l dyBzaWduYWwgd2lsbCBhbHdheXMgYmUgdGhlIHZhbHVlIG9mClNJR05BTC4gIFRoaXMgc2lnbmFs IGlzIGEgY29udmVuaWVudCB3YXkgdG8gc25lYWsgYSBwcm9jZWR1cmUgdGhhdCBoYXMKYSBzaWRl LWVmZmVjdCBpbnRvIGEgc2lnbmFsIGNoYWluLiIKICAoc2lnbmFsLW1hcCAobGFtYmRhICh4KSAo cHJvYyB4KSB4KSBzaWduYWwpKQo= --=-=-=--