source: project/gazette/src/issues/21.wiki @ 25560

Last change on this file since 25560 was 25560, checked in by andyjpb, 8 years ago

Gazette 21: The bootstrap chicken must be installed!

File size: 32.9 KB
Line 
1((title . "Issue 21")
2 (authors "Andy Bennett")
3 (date . 1321465864))
4
5== 0. Introduction
6
7Welcome to the 21st issue of the Chicken Gazette.
8
9In this issue we have updates on several parts of the Chicken community,
10including trips, meetups, eggs, testing as well as developments in the core itself.
11Over in [[#omelette-recipes|the Omelette section]] we have the second installment of
12[[http://wiki.call-cc.org/users/alaric-blagrave-snellpym|Alaric Snell-Pym]]'s
13much coveted "financial book-keeping in scheme" series.
14
15Rounding up all the changes since the last edition has been a rather involved
16task which wouldn't have been possible without the friendly help of all my
17contributors and fellow editors in the
18[[http://wiki.call-cc.org/discussion-groups#irc|#chicken chat channel]], so
19many, many thanks are due to them. Also, if you haven't already joined us in
20[[http://wiki.call-cc.org/discussion-groups#irc|#chicken]], pop in and chat about
21Chicken specific aspects of scheme.
22
23
24Enjoy and look out for issue 22 soon!
25
26
27== 1. Chickens Out & About
28
29=== Nuremberg (December 2011)
30[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] wrote
31([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00114.html|2011/10/22 17:38Z]]) to
32confirm the planned Chicken Hacking Sprint scheduled for the beginning of December.
33
34Interested and available Chickenauts will meet in Nuremberg on the weekend of 9th, 10th and 11th
35of December. If you haven't done so already, you can let us know that you will be joining us by
36placing a note at the foot of the [[https://wiki.call-cc.org/chicken-sprint-nuremberg|wiki page]].
37If you can't attend in person then we'll be keeping an eye on IRC so feel free to book yourself
38a slot in your cave at home and join us throughout the weekend and into the evenings, Central European Time.
39
40For those of you keeping score, this will bring the total number of Chicken meets this year to
415 (FOSDEM, Cologne, FrOSCon, T-DOSE and Nuremberg).
42
43
44=== Cologne (March 2011)
45
46In March, Chickens met up at the Chaos Computer Club in Cologne, Germany for a Chicken Hacking Weekend. Here's
47[[http://wiki.call-cc.org/users/moritz-heidkamp|Moritz Heidkamp]]'s report on what they got up to.
48
49The usual suspects [[user:peter-bex|Peter Bex]],
50[[user:felix-winkelmann|Felix Winkelmann]],
51[[user:christian-kellermann|Christian Kellermann]] and me met for two
52and a half days of exchanging ideas and hacking. While we also fixed a
53good share of bugs our main goal for this weekend was to create a
54working prototype of a distributed egg system. By the end of Sunday,
55mostly thanks to Peter's effort, we had something that was already
56pretty similar to what is in use today (see
57[[http://lists.nongnu.org/archive/html/chicken-users/2011-03/msg00160.html|his announcement on the mailing list]]). Apart
58from that some interested visitors stopped by every now and then. Some
59nice chats, food and the occasional beers were had which hopefully
60helped to spread the Chicken word.
61
62
63=== FrOSCon (August 2011)
64At FrOSCon in August we sported not only a project booth but a presentation room as well so we took the
65opportunity to lay on a couple of talks for the delegates.
66
67[[http://wiki.call-cc.org/users/moritz-heidkamp|Moritz Heidkamp]] presented
68"[[http://programm.froscon.org/2011/events/869.html|An introduction to Lisp]]:
69Why to talk to computers in parentheses" whilst
70[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] offered
71"[[http://programm.froscon.org/2011/events/867.html|A guided tour through the republic of CHICKEN]]:
72get up to speed with the practical scheme implementation".
73[[http://wiki.call-cc.org/users/christian-kellermann|Christian]] has been keeping his talk up-to-date and
74you can find the latest version [[http://wiki.call-cc.org/chickenista-guide|on the wiki]].
75
76Naturally, there are [[http://www.call-cc.org/pictures/froscon2011/|pictures]].
77
78
79=== T-DOSE 2011 (November 2011)
80European Chickens met up at T-DOSE in Eindhoven, The Netherlands on the weekend of the 5th, 6th and 7th of
81November. [[http://wiki.call-cc.org/users/peter-bex|Peter Bex]] arranged for us to contribute a "Chicken
82Scheme Project Booth" and we subsequently lured a few Dutch hackers into #chicken on IRC.
83
84[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] knocked up some impressive demos
85of [[http://en.wikipedia.org/wiki/Pong|PONG]] using Chicken's [[http://wiki.call-cc.org/eggref/4/cairo|Cairo Egg]].
86
87[[http://wiki.call-cc.org/users/alaric-blagrave-snellpym|Alaric Snell-Pym]] finished off the tests for his
88[[http://wiki.call-cc.org/eggref/4/ugarit|Ugarit]] backup egg which allowed him to release version 1.0.
89
90...and [[http://wiki.call-cc.org/users/moritz-heidkamp|Moritz Heidkamp]] started on a replacement for the
91[[http://wiki.call-cc.org/eggref/4/environments|Environments Egg]] as it has unfortunately has been overtaken
92by developments in the Chicken development branch.
93
94Pictures are up in the [[http://www.call-cc.org/pictures/t-dose2011/|usual place]] on the Chicken website.
95
96
97
98== 2. Chicken Talk
99
100=== R7RS to be dedicated to the memory of John McCarthy
101
102Matt Welland wrote in with the sad news that the "Father of Lisp", John McCarthy had sadly passed away ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00115.html|2011/10/25 15:59Z]]). [[http://wiki.call-cc.org/users/john-cowan|John Cowan]], member of the R7RS working group, told us that R7RS,
103the upcoming version of the Scheme standard, would be dedicated to his memory ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00116.html|16:22Z]])
104
105
106=== Parallel build patch for Chicken Makefile
107
108A lively discussion broke out on the [[https://wiki.call-cc.org/mailing-lists|Chicken Users mailing list]] regarding
109[[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00025.html|parallelisation of the Chicken build process]].
110
111Vitaly Magerya supplied a [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00025.html|patch]] (2011/10/06 12:37Z) to fix some problems
112he'd been having with builds failing when specifying the {{-j}} to {{gmake}}.
113[[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario Domenech Goulart]] noted that this functionality was already being
114addressed by [[http://bugs.call-cc.org/ticket/526|ticket 526]]
115([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00027.html|2011/10/06 12:39Z]]) and Vitaly was keen to see it committed
116soonly as he maintains the FreeBSD port and people had been asking him for parallel builds ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00028.html|2011/10/06 14:24Z]]). Whilst still keen, [[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00029.html|advised caution]] as he wanted to see it proven ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00031.html|2011/10/06 14:40Z]]).
117
118Vitaly was keen to push things forward ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00033.html|2011/10/06 15:45Z]]) and
119offered continued testing under FreeBSD 8.2-RELEASE on x86_64. He noted that, as far as he could tell, {{gmake check}} passed when using his
120patch, modified with [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00026.html|Moritz Wilhelmy's suggestions]]. Moreover, he
121offered to try the patch from [[http://bugs.call-cc.org/ticket/526|ticket 526]] as well.
122
123[[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00034.html|suggested]]
124that using the [[http://bugs.call-cc.org/ticket/526|ticket 526]] patch was a good idea as it had, as far as he knew, received testing under Linux and MacOSX.
125
126Toby Thain spoke in favour of the patch, saying that a working parallel build gives confidence that the Makefile is, in fact, correct.
127He offered to test on three platforms, namely Solaris 10 SPARC SMP and both PowerPC and Intel version of MacOSX SMP.
128
129Vitaly updated the [[http://bugs.call-cc.org/ticket/526|ticket 526]] patch to the then current sources and confirmed that the build worked at {{-j8}}
130and the tests passed in his FreeBSD 8.2-RELEASE, x86_64 environment. He did, however, note that parallelisation does not work for the install phase
131([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00048.html|2011/10/08 12:29Z]]).
132
133Toby Thain reported successful builds on the 64-bit version MacOSX-10.6 as well as MacOSX-10.5 on a dual-processor G5. He noted "{{make -j8}}
134reduces the make step from 3:39 to 0:47 on my 8-core system". Unfortunately {{make check}} did not pass on either system, with or without the patch
135([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00071.html|2011/10/12 01:59Z]] &
136[[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00100.html|2011/10/15 19:53Z]])
137
138[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] noted that it might necessary to install the compiled binaries
139([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00101.html|2011/10/15 20:07Z]]) however, Toby did not report back as to whether this
140had any effect on the results of the tests.
141
142
143=== 64-bit SPARC Build
144
145Nicolas Pelletier came to the [[https://wiki.call-cc.org/mailing-lists|mailing list]]
146unable to build for Solaris 10 running on SPARC64 due to a missing {{apply-hack.S}}
147([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00012.html|2011/11/09 11:48Z]]).
148
149It turned out that there was no SPARC64 support for Chicken at all and [[http://wiki.call-cc.org/users/john-cowan|John Cowan]]
150came to the rescue ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00013.html|15:36Z]])
151with instructions for how to add it to the supported architectures list and disable the
152apply hack. [[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] chimed in with affirmations
153around the utility of using Chicken without an apply hack ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00014.html|15:54Z]])
154
155Nicolas struggled with disabling the apply hack ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00015.html|2011/11/10 11:10Z]])
156due to the Two Lies Of The README. Over the course of the next few minutes [[http://wiki.call-cc.org/users/christian-kellermann|Christian]]
157and [[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario Domenech Goulart]]
158confirmed that the lies, which related to the way bootstrap compilers are distributed and invoked, had
159already been fixed in the development versions.
160
161Meanwhile, Toby Thain tried the build on his SPARC64 ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00020.html|12:40Z]])
162and discovered that GNU make 3.82 is required as well as the addition of {{-lrt}} in {{Makefile.solaris}}. Toby's
163build eventually succeeded and appeared to be good, albeit having only used 1 of his 4 CPUs and with a couple of {{make check}} errors.
164
165Later on the Thursday, [[http://wiki.call-cc.org/users/jim-ursetto|Jim Ursetto]] noted ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00021.html|16:47Z]])
166that the [[http://bugs.call-cc.org/raw-attachment/ticket/526/parallel-build-2.diff.txt|parallel build patch]] in
167[[http://bugs.call-cc.org/ticket/526|ticket 526]] still works on Chicken 4.7.0.3-st. Toby [[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00022.html|confirmed]]
168that the patch did indeed work on Solaris and build time was reduced to 10 just of his Earth minutes from the original 40.
169Of course, user time across the four CPUs was still in the region of 40 minutes in total. :-)
170
171To round everything off, Toby offered [[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00028.html|binary SYSV packages for Solaris 10 on SPARC64]].
172Contact him via the [[https://wiki.call-cc.org/mailing-lists|mailing list]] if you're interested.
173
174
175=== Static Linking & Standalone Binaries.
176
177Serg Kozhemyakin [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00105.html|asked]] whether it is possible to build static
178binaries after having trouble using the {{-static}} flag to {{csc}}. He also wondered about building standalone binaries for Windows.
179[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00106.html|advised]]
180against static linking as many of the eggs cannot cope with it. He did, however, suggest that the {{-deploy}} option may well solve both
181issues as it ensures that all the DLLs (including the Chicken runtime and other shared objects) are bundled together into a single directory.
182
183
184=== Tracing with {{,tr}} moved to an egg
185
186[[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario Domenech Goulart]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00007.html|helped]]
187Curtis Cooley in his [[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00006.html|search for the {{,tr}} command]].
188The functionality had been moved from the core into an egg in Chicken 4.3.0.
189
190
191=== {{gmake check}} sometimes fails.
192
193Pekka Niiranen wrote to tell us about
194[[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00009.html|problems with {{gmake check}} in Chicken 4.7.0-st]]
195on OpenBSD 5.0.
196
197[[http://wiki.call-cc.org/users/jim-ursetto|Jim Ursetto]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00010.html|said]]
198that one of the failures had been fixed in the stability branch after the Chicken 4.7.0-st release and he filed
199[[https://bugs.call-cc.org/ticket/724|ticket 724]] for the segmentation fault issue.
200
201[[http://wiki.call-cc.org/users/peter-bex|Peter Bex]] mentioned that the [[https://bugs.call-cc.org/ticket/724|ticket 724]] segmentation
202fault had also been observed under NetBSD and Arch Linux. He said that "It's known to be broken" but that it is not properly reproducible
203as it only happens some of the time ([[http://lists.nongnu.org/archive/html/chicken-users/2011-11/msg00011.html|2011/11/06 09:51|]]).
204
205
206== 3. Salmonella and other tests
207Salmonella is Chicken's egg testing framework.
208
209For some time we have had daily salmonella runs of the master development
210version of Chicken under Linux on x86. Throughout November, MacOSX-x86_64 has also
211been regularly experiencing the runs. [[http://wiki.call-cc.org/users/mario-domenech-goulart|Mario Domenech Goulart]] who maintains the testing
212effort at [[http://tests.call-cc.org/]], as well as the [[https://github.com/mario-goulart/salmonella|Salmonella codebase]]
213itself, is always on the lookout for more feeds. We are aware that testing on
214other platforms is being organised but if you've got a private Salmonella
215running regularly on an interesting operating system or version of Chicken then
216give us a shout and we'll see if we can get it included with the other reports
217on [[http://tests.call-cc.org/]]
218
219There is also [[https://github.com/mario-goulart/salmonella|an entirely new version of Salmonella]] over at github so test that too. The new version is more modular -- some features that were previously built in salmonella are now independent eggs (e.g., [[https://github.com/mario-goulart/salmonella-html-report|salmonella-html-report]] and [[https://github.com/mario-goulart/salmonella-feeds|salmonella-feeds]]).  There's also a new egg that provides a new feature: [[https://github.com/mario-goulart/salmonella-diff|salmonella-diff]] which generates HTML output to render differences between two salmonella logs.
220
221Here's short list of new salmonella features:
222
223* egg lint mode: salmonella can now easily check for common egg mistakes before the code hits the egg repository.  Just run {{salmonella --this-egg}} from the egg directory
224* a new execution mode that can significantly reduce salmonella execution times.  In this mode, salmonella won't set the temporary egg installation directory empty before installing new eggs.  While this mode won't spot egg dependencies problems, it can drastically effect the execution time
225* a new tool to take advantage of multi-core systems ({{salmonella-epidemy}})
226* a simple text mode log file viewer ({{salmonella-log-viewer}})
227* [[https://github.com/mario-goulart/salmonella-html-report|salmonella-html-report]] generates reverse dependencies graphs.  That can be useful, for
228example, to ilustrate how many eggs depend on a given egg.
229
230
231[[http://wiki.call-cc.org/users/alaric-blagrave-snellpym|Alaric Snell-Pym]] is one of the people who has been setting up a Chicken testing
232environment. After [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00068.html|some discussion]], he chose Chicken 4.5.0 under
233NetBSD ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00035.html|2011/10/06 21:18Z]]). He's been keeping track of all the
234Egg dependencies and plans to publish them as a list of NetBSD pkgsrc packages.
235
236Thanks to [[http://www.bevuta.com/|bevuta IT GmbH]], the CHICKEN test
237infrastructure will soon have more machines available to test the
238CHICKEN compiler, tools and eggs.  A new salmonella environment for
239Linux/x86-64 is currently being set up.
240
241In addition to salmonella, work on the
242[[http://wiki.call-cc.org/playground|Chicken Playground]] project has
243been resumed.  The Chicken Playground project provides environments
244that can be used by tools like {{chroot}} to test CHICKEN tools and
245eggs.  Those environments contain tools and libraries required to
246build and test most eggs.  Currently a Linux/x86 environment is
247available. A Linux/x86-64 environment is under development and should
248be available soon.
249
250The new test infrastructure, based on new versions of salmonella and
251Chicken Playground and running on new platforms will probably go into
252production during the Nuremberg hackaton.
253
254
255== 4. Core Development
256
257Since the last issue most core development took place in the
258"scrutinizer", the flow-analysis pass used for determining the number
259and types of values as they propagate through Scheme expressions. The
260results of this analysis is now used to replace various primitive
261operations by more efficient code, taking advantage of the obtained
262type information. Over the last months the typing and rewrite rules of
263all core library procedures (which can be found in the installed
264"types.db" file) have been heavily improved and debugged. Depending on
265the nature of the code, these optimizations can result in significant
266performance improvements. For more information on specialisation see
267the respective section at
268[[http://library.readscheme.org/page10.html|readscheme.org]].
269
270A couple of months ago the CHICKEN team has formalised the development
271process a bit as can be seen on
272[[http://wiki.call-cc.org/development-process|its wiki page]]. Others
273already joined in the discussion of patches on the
274[[https://lists.nongnu.org/mailman/listinfo/chicken-hackers|chicken-hackers mailing list]]
275and you are more than welcome to join in.
276
277As more people are trying git checkouts, the question of how to
278bootstrap a git checkout properly keeps reappearing on the mailing
279list. So the steps are:
280
281* Build & install a [[http://code.call-cc.org|stable release]] or a [[http://code.call-cc.org/dev-snapshots|development snapshot]]
282* Checkout chicken-core from git (see [[http://code.call-cc.org]])
283* Build a boot-chicken: {{make boot-chicken}}
284* Use this chicken to build the real chicken: {{make CHICKEN=./chicken-boot}}
285* Install the chicken and run tests: {{make install && make check}}
286
287
288
289== 5. Stability is for Chickens
290
291[[http://wiki.call-cc.org/users/jim-ursetto|Jim Ursetto]] has set up a Chicken Stability Branch
292effort over at [[http://wiki.call-cc.org/stability]]. Jim describes it as "a fork of the Chicken
293Scheme core which backports certain useful bugfixes and minor features from the future to 'stable'
294maintenance versions". Releases for stability/4.7.0 have version numbers like {{4.7.0.x-st}} (for
295example, {{4.7.0.1-st}}). If you're interested in running a stable Chicken in production, we recommend
296that you check out Jim's work.
297
298
299
300== 6. Hatching Farm
301
302There has been a lot of egg activity over the course of the past few months. I've selected a few,
303focussing on ones that were announced or discussed on the [[https://wiki.call-cc.org/mailing-lists|mailing list]].
304
305By far the most notable thing to have happened is the announcment and implementation of the new
306[[http://lists.nongnu.org/archive/html/chicken-users/2011-03/msg00160.html|distributed egg system]],
307written by Chicken Hackers during the [[#cologne-march-2011|Cologne Chicken Meetup in March]].
308
309* [[http://wiki.call-cc.org/users/ivan-raikov|Ivan Raikov]]'s [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00058.html|proposal]]
310  to recategorise eggs filed under "Uncategorized or invalid" and "Miscellaneous" was met with enthusiasm with a number of people pitching in to
311  help as well as [[http://wiki.call-cc.org/users/peter-bex|Peter Bex]] suggesting that the category list be revisited
312  ([[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00064.html|2011/10/11 08:12Z]]). [[http://wiki.call-cc.org/users/peter-bex|Peter]]
313  specifically suggested the addition of a "Communication"s category.
314
315* [[http://wiki.call-cc.org/users/thomas-chust|Thomas Chust]] announced some new eggs: [[http://www.chust.org/fossils/webkit|bindings to WebKitGTK+ and JavaScriptCore]], [[http://www.chust.org/fossils/webgate|webgate: a tiny (S)CGI application framework]] and a [[http://www.chust.org/fossils/berkeley-db|small binding for the BerkelyDB library]]
316
317* [[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]]
318  [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00103.html|fixed some bugs]] in the
319  [[http://wiki.call-cc.org/eggref/4/cairo|Cairo Egg]] and tagged version 0.1.11.
320
321* [[http://wiki.call-cc.org/users/alyn.post|Alan Post]] [[http://lists.nongnu.org/archive/html/chicken-users/2011-10/msg00001.html|patched]] the
322  [[http://wiki.call-cc.org/eggref/4/sandbox|Sandbox Egg]] to bring it up-to-date with API changes in the Chicken core. His patch was duly accepted.
323 
324* [[user:moritz-heidkamp|Moritz Heidkamp]] released the [[egg:stemmer|stemmer]] egg which provides bindings for the [[http://snowball.tartarus.org/|Snowball project's]] libstemmer.
325
326
327
328== 7. Donations
329
330It's now possible to donate to your favourite scheme (as long as it's Chicken)!
331
332[[http://wiki.call-cc.org/donate]]
333
334We've already had two donations since the account opened a month ago so get donating before it fills up! :-)
335
336Thank you [[http://wiki.call-cc.org/users/sven-hartrumpf|Sven Hartrumpf]] and Ross Lonstein!
337
338
339== 8. Omelette Recipes
340
341This issue's omelette is the second installment of
342[[http://wiki.call-cc.org/users/alaric-blagrave-snellpym|Alaric Snell-Pym]]'s
343"financial book-keeping in scheme" series. If you missed the first part,
344check it out [[http://gazette.call-cc.org/issues/20.html#omelette-recipes|here]].
345
346Now, to make things easy, I parse the ledger by just defining a heap
347of procedures and macros, and then diving into the ledger with
348eval. It's just Scheme code that, as it is executed, builds up the
349data structures. We'll need some helpers to set up third parties
350properly:
351
352<enscript>
353(define (define-third-party name address group)
354  (let* ((balance-account
355          (make-account
356           (string-append name ".balance")
357           'balance
358           group
359           #f))
360         (expenses-account
361          (make-account
362           (string-append name ".expenses")
363           'delta
364           'expenses-reclaimed
365           #f))
366         (third-party
367          (make-third-party
368           name address balance-account expenses-account)))
369    (account-third-party-set! balance-account third-party)
370    (account-third-party-set! expenses-account third-party)
371    (register-account! balance-account)
372    (register-account! expenses-account)
373    (set! (hash-table-ref *third-parties* name) third-party)))
374</enscript>
375
376Now we can work on a way of representing bills and invoices. A nice
377input syntax would be:
378
379<enscript>
380(define-third-party "clients.widgetcorp" "123 Any Street" 'clients)
381(register-account! (make-account "income.work" 'delta 'income #f))
382(register-account! (make-account "expenses.travel" 'delta 'travel #f))
383(register-account! (make-account "stock.balance" 'balance 'stock #f))
384(register-account! (make-account "cash" 'balance 'cash #f))
385(register-account! (make-account "taxes.vat" 'balance 'vat #f))
386
387(invoice "INV005" "clients.widgetcorp" (ymd 2011 04 25)
388         (service "income.work" 800 (vat20) "Router setup and installation")
389         (sale "stock.balance" 350 (vat20) "1 of LX300 router, serial number 0343248")
390         (expense (ymd 2011 03 02) "expenses.travel" "cash" 35 () "Travel to site"))
391</enscript>
392
393The idea is that the sales taxes incurred on a line are specified as a
394list after the amount. If there's no taxes due, then we use an empty
395list. Otherwise we have a list of taxes, which are either plain tax
396names (to have the system compute the tax due itself) or two-element
397lists joining a tax name to a precomputed amount (often, when we pass
398on an expense, we know the tax we paid as it's on the receipt, so we
399should use that (even if they made a mistake working it out) rather
400than calculating our own).
401
402A nice way to implement that might be to make "invoice" a macro that
403absorbs its first three arguments as an invoice code, the name of the
404third party to invoice, and the date; then treats the rest as a body
405to be wrapped in a dynamic environment in which a parameter allows
406{{sale}}, {{expense}}, and {{service}} to add lines to the
407invoice. This is easily arranged:
408
409<enscript>
410(define-record date year month day)
411
412(define-record invoice
413  name date third-party lines)
414
415(define (register-line! invoice line)
416  (invoice-lines-set! invoice
417                      (cons line (invoice-lines invoice))))
418
419;; Compute sales taxes
420(define (compute-tax tax amount)
421  (case tax
422    ((vat20) (* 0.20 amount)) ;; Current UK rate
423    ((vat15) (* 0.15 amount)) ;; Previous UK rate
424    ((vat175) (* 0.175 amount)))) ;; Previous UK rate
425
426;; Expand a list of taxes, some of which might be bare symbols
427;; naming taxes to work out, or (<tax> <amount>) lists for
428;; ready-computed taxes, into an alist of tax names to tax amounts
429(define (resolve-taxes amount taxes)
430  (map (lambda (tax-desc)
431         (if (list? tax-desc)
432             (cons (car tax-desc) (cadr tax-desc))
433             (cons tax-desc (compute-tax tax-desc amount))))
434       taxes))
435
436(define-record invoice-service-line
437  income-account amount taxes description)
438
439(define-syntax service
440  (syntax-rules ()
441    ((service income-account amount taxes description)
442     (register-service! (*current-invoice*) income-account amount 'taxes description))))
443
444(define (register-service! invoice income-account amount taxes description)
445  (let ((service
446         (make-invoice-service-line
447          (find-account income-account)
448          amount
449          (resolve-taxes amount taxes)
450          description)))
451    (register-line! invoice service)))
452
453(define-record invoice-sale-line
454  stock-account amount taxes description)
455
456(define (register-sale! invoice stock-account amount taxes description)
457  (let ((sale
458         (make-invoice-sale-line
459          (find-account stock-account)
460          amount
461          (resolve-taxes amount taxes)
462          description)))
463    (register-line! invoice sale)))
464
465(define-syntax sale
466  (syntax-rules ()
467    ((sale stock-account amount taxes description)
468     (register-sale! (*current-invoice*) stock-account amount 'taxes description))))
469
470(define-record invoice-expense-line
471  expense-account payment-account amount taxes description)
472
473(define (register-expense! invoice date expense-account payment-account amount taxes description)
474  (let ((expense
475         (make-invoice-expense-line
476          (find-account expense-account)
477          (find-account payment-account)
478          amount
479          (resolve-taxes amount taxes)
480          description)))
481    (register-line! invoice expense)))
482
483(define-syntax expense
484  (syntax-rules ()
485    ((expense (ymd year month day) expense-account payment-account amount taxes description)
486     (register-expense!
487      (*current-invoice*)
488      (make-date year month day)
489      expense-account
490      payment-account
491      amount
492      'taxes
493      description))))
494
495(define *current-invoice* (make-parameter #f))
496(define *invoices* (make-hash-table))
497
498(define-syntax invoice
499  (syntax-rules (service sale expense)
500    ((invoice name third-party (ymd year month day) body ...)
501     (let ((inv
502            (make-invoice name
503                          (make-date year month day)
504                          (hash-table-ref *third-parties* third-party)
505                          '())))
506       (parameterize
507        ((*current-invoice* inv))
508        (begin body ...))
509       (set! (hash-table-ref *invoices* name) inv)
510       (generate-invoice-transactions! inv)))))
511</enscript>
512
513We end the expansion of the {{invoice}} macro with a call to
514{{generate-invoice-transactions!}}, which will do the task of creating
515the double-entry transactions for the invoice. Other types of summary
516structure can be added by calling additional generator procedures at
517this point. This is largely a matter of going through the invoice
518lines, handling them on a case-by-case basis to generate lists of
519transaction splits that we can append together to generate the invoice
520transaction. The case of expense lines is interesting, in that an
521extra transaction has to be generated for each expense, to record its
522initial spending, as well as a split to record the expense being
523claimed in the invoice.
524
525For now, let's just handle one case:
526
527<enscript>
528(define (generate-invoice-transactions! inv)
529  (register-txn! (make-txn
530    (invoice-date inv)
531    (string-append "Invoice " (invoice-name inv) " for "
532                   (third-party-full-name (invoice-third-party inv)))
533    (let ((txn-balance-account
534           (third-party-balance-account
535            (invoice-third-party inv))))
536      (flatten
537       (map
538        (lambda (line)
539          (cond
540           ((invoice-expense-line? line)
541            (list)) ;; FIXME: Not implemented
542           ((invoice-sale-line? line)
543            (list)) ;; FIXME: Not implemented
544           ((invoice-service-line? line)
545            (list
546             (make-txn-split
547              (invoice-service-line-income-account line)
548              (- (invoice-service-line-amount line))
549              (invoice-service-line-description line))
550             (make-tax-splits
551              (invoice-service-line-taxes line)
552              txn-balance-account)
553             (make-txn-split
554              txn-balance-account
555              (invoice-service-line-amount line)
556              #f)))))
557        (invoice-lines inv)))))))
558
559(define (make-tax-splits taxes txn-balance-account)
560  (map (lambda (tax)
561         (let ((tax-type (car tax))
562               (tax-amount (cdr tax)))
563           (case tax-type
564             ((vat20 vat15 vat175)
565              (list
566               (make-txn-split
567                (find-account "taxes.vat")
568                (- tax-amount)
569                #f)
570               (make-txn-split
571                txn-balance-account
572                tax-amount
573                #f))))))
574       taxes))
575</enscript>
576
577Feeding in the above example invoice, then checking out the resulting
578double-entry transaction list, shows that it worked:
579
580<enscript>
581(hash-table-for-each *txns*
582                     (lambda (date txns)
583                       (for-each
584                        (lambda (txn)
585                          (printf "Date: ~A Desc: ~A\n"
586                                  (txn-date txn)
587                                  (txn-description txn))
588                          (for-each (lambda (split)
589                                      (printf "Acct: ~A Delta: ~A Notes: ~A\n"
590                                              (account-name (txn-split-account split))
591                                              (txn-split-amount split)
592                                              (txn-split-notes split))) (txn-splits txn)))
593                        txns)))
594</enscript>
595
596   date: #<date> Desc: Invoice INV005 for Widget Corp
597   Acct: income.work Delta: -800 Notes: Router setup and installation
598   Acct: taxes.vat Delta: -160.0 Notes: #f
599   Acct: clients.widgetcorp.balance Delta: 160.0 Notes: #f
600   Acct: clients.widgetcorp.balance Delta: 800 Notes: #f
601
602We've ended up with multiple splits for the same account, as we record
603that both VAT and the money due for the service are to come from the
604client's balance account - and other splits will add plenty more. To
605fix this, we need to write a procedure that canonicalises a list of
606splits, and call that on the splits before calling
607{{make-txn}}. Canonicalisation consists of finding all the splits that
608refer to the same account and have the same notes (be it {{#f}} or a
609string) and merging them into one with the total of the amounts. But
610I'll leave that (along with implementing bills, payments, and some
611actual reports) as an exercise to the reader... It's easy to imagine
612how to generate a VAT report from the list of transactions, by
613filtering them for membership of the required date range and looking
614for splits involving "taxes.vat", or to generate a nicely formatted
615invoice by extracting a single invoice record, or to work out the
616balance of an account at any point in time by adding up all the
617transaction splits that involve it up to that point in time. Also, the
618core engine needs to be wrapped up in a module that only exposes the
619required bindings, and hides internals.
620
621Having automated one's book-keeping and financial reporting, many
622operations (such as the VAT returns) can be done without involving an
623accountant; in my case, the accountant is only needed to help with the
624annual corporation tax computation and filing of official accounts,
625which requires deep understanding of the UK tax system to do
626everything properly. Having said that, if I studied the system
627properly (and tracked the changes each year), I'm sure I could
628automate that, too...
629
630== 9. About the Chicken Gazette
631
632The Gazette is produced occasionally by a volunteer from the Chicken
633community. The latest issue can be found at
634[[http://gazette.call-cc.org]] or you can follow it in your feed
635reader at [[http://gazette.call-cc.org/feed.atom]]. If you'd like to
636write an issue, [[http://wiki.call-cc.org/gazette|consult the wiki]]
637for the schedule and instructions!
Note: See TracBrowser for help on using the repository browser.