I'm using the R5RS as a guideline for what needs to be there. Since I don't have a full numeric tower but only fixnums (I will probably add floats later), I only implemented the integer predicates and operations. I will also probably need to add vectors. Here's a list of what's available so far:
- Equivalence predicates
- eq?
- Numerical operations
- number?, integer?, =, <, >, <=, >=, zero?, positive?, negative?, odd?, even?, max, min, +, *, -, /, abs
- Booleans
- not, boolean?
- Pairs and Lists
- pair?, cons, car, cdr, set-car!, set-cdr!, caar, cadr, cdar... cddddr, null?, list?, list, length, append, reverse, list-tail, list-ref
- Symbols
- symbol?, symbol->string, string->symbol
- Characters
- char?, char=?, char?, char<=?, char>=? (and the case insensitive version of these), char-alphabetic?, char-numeric?, char-whitespace?, char-upper-case?, char-lower-case?, char->integer, integer->char, char-upcase, char-downcase
- Strings
- string?, make-string, string, string-length, string-ref, string-set!, string=?, string?, string<=?, string>=? (and their -ci counterparts)
There is one particular implementation note for the comparison predicates on integers, characters and string. I wrote them as preprocessor macros. Here's a gist:
I used macros not so much to save typing, but to avoid copy-pasting mistakes. These functions have the same structure, they only differ in what is being tested. Poor man's higher order procedures. Note the "identity" case-folding macro for the case sensitive versions.
The strings weren't so easy, particularly at early morning hours. The added complication is that two character-wise equal strings up to the length of the shortest string, have an additional ordering imposed by the length of the strings.
Enter unit tests. I'm somewhat of a heretic these days, as I don't usually write unit tests on a regular basis. If you write in C, they tend to become extremely verbose for what amounts to some very simple tests, and they slow me down.
This however is a perfect example of a situation where I find them useful: mindlessly adding small bits of code with limited functional goals, until the final product is complete and can be tested.
In this particular situation, it was very convenient to be able to test primitives as I was adding them, so I put together a small perl script to run the 73 simple tests and 303 primitive tests. As opposed to writing C unit tests, these were really easy to add.
I count 6 commits that fix primitive bugs and one for the reader. In reality, there were more like 10 bugs, not 6.
Niciun comentariu:
Trimiteți un comentariu