From 4210e8538e6e0adf3af7badeab33c619f3db9497 Mon Sep 17 00:00:00 2001 From: Taylan Kammer Date: Fri, 26 Dec 2025 07:09:36 +0100 Subject: Add a note, expand other notes, add dates into notes. --- html/index.md | 2 ++ notes/250210-booleans.md | 2 ++ notes/250210-compile.md | 2 ++ notes/250210-cons.md | 2 ++ notes/250210-equal.md | 2 ++ notes/250210-immutable.md | 2 ++ notes/250210-let.md | 2 ++ notes/250210-nan.md | 2 ++ notes/250210-records.md | 2 ++ notes/250210-serialize.md | 2 ++ notes/250210-strict-mode.md | 2 ++ notes/250210-sugar.md | 2 ++ notes/250210-symbols.md | 2 ++ notes/250210-zero-values.md | 2 ++ notes/250219-format.md | 2 ++ notes/250219-reader.md | 2 ++ notes/250228-macros.md | 2 ++ notes/250228-sr.md | 2 ++ notes/250317-fastcons.md | 2 ++ notes/250329-boot.md | 18 +++++++++++- notes/250329-numbers.md | 27 +++++++++++++++++- notes/250920-goals.md | 67 +++++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 notes/250920-goals.md diff --git a/html/index.md b/html/index.md index 2c87c45..77f74e7 100644 --- a/html/index.md +++ b/html/index.md @@ -33,5 +33,7 @@ because writing the code often gives you yet another perspective. * [Does the decoder implement macros?](notes/250228-macros.html) * [Better syntax-rules?](notes/250228-sr.html) * [Cons cell optimization?](notes/250317-fastcons.html) +* [Bootstrapping](notes/250329-numbers.html) * [Bootstrapping](notes/250329-boot.html) * [Using libgccjit?](notes/250920-libgccjit.html) +* [Goals](notes/250920-goals.html) diff --git a/notes/250210-booleans.md b/notes/250210-booleans.md index 61b9d7e..b26e101 100644 --- a/notes/250210-booleans.md +++ b/notes/250210-booleans.md @@ -1,5 +1,7 @@ # Only Booleans have truthiness +_2025 February_ + Like in Java, there should be no implicit conversion of values to a Boolean. This leads to sloppy code and subtle bugs. diff --git a/notes/250210-compile.md b/notes/250210-compile.md index 4d5fc6d..3cd8831 100644 --- a/notes/250210-compile.md +++ b/notes/250210-compile.md @@ -1,5 +1,7 @@ # Compilation is execution +_2025 February_ + Any Scheme implementation with support for procedural macros allows arbitrary code execution at compile-time. However, this is slightly awkward: diff --git a/notes/250210-cons.md b/notes/250210-cons.md index 29bb2d6..3146957 100644 --- a/notes/250210-cons.md +++ b/notes/250210-cons.md @@ -1,5 +1,7 @@ # Stop the "cons" madness! +_2025 February_ + Lists are neat, but they aren't the best representation for sequences of fixed length. An array/vector is a better choice for this. diff --git a/notes/250210-equal.md b/notes/250210-equal.md index 8c55faa..e81defb 100644 --- a/notes/250210-equal.md +++ b/notes/250210-equal.md @@ -1,5 +1,7 @@ # A novel approach to object equivalence +_2025 February_ + ## Story time In my past 5 years of developing a warehouse management application, diff --git a/notes/250210-immutable.md b/notes/250210-immutable.md index 78652e9..fddc0d8 100644 --- a/notes/250210-immutable.md +++ b/notes/250210-immutable.md @@ -1,5 +1,7 @@ # More immutability +_2025 February_ + I see no reason to have mutable variables in the language. Usually, code is analyzed to distinguish between mutable and immutable diff --git a/notes/250210-let.md b/notes/250210-let.md index 4af41bd..7fc27d4 100644 --- a/notes/250210-let.md +++ b/notes/250210-let.md @@ -1,5 +1,7 @@ # No shadowing (shock!) and a reduced set of `let` forms +_2025 February_ + This may be shocking for Schemers but I believe shadowing variables is evil. I've already written a bug once that would have been prevented had it not been possible to shadow variables, and I don't even write diff --git a/notes/250210-nan.md b/notes/250210-nan.md index f8f3f80..2824237 100644 --- a/notes/250210-nan.md +++ b/notes/250210-nan.md @@ -1,5 +1,7 @@ # NaN-Packing +_2025 February_ + NaN-packing (also called NaN-boxing) is a strategy involving the use of NaN bit patterns, that are otherwise unused, to store various values in them. diff --git a/notes/250210-records.md b/notes/250210-records.md index b93e0c3..02772f5 100644 --- a/notes/250210-records.md +++ b/notes/250210-records.md @@ -1,5 +1,7 @@ # Subtyping of record types +_2025 February_ + It's a serious limitation of SRFI 9 that it doesn't allow creating subtypes with additional fields. This is an invaluable strategy for representing a hierarchy of types, which are ubiquitious in real life diff --git a/notes/250210-serialize.md b/notes/250210-serialize.md index 8e5d49b..3def658 100644 --- a/notes/250210-serialize.md +++ b/notes/250210-serialize.md @@ -1,5 +1,7 @@ # Everything can be serialized +_2025 February_ + Let's look at the code mentioned in [compilation](compile.html) again: ```scheme diff --git a/notes/250210-strict-mode.md b/notes/250210-strict-mode.md index 5b99386..c059775 100644 --- a/notes/250210-strict-mode.md +++ b/notes/250210-strict-mode.md @@ -1,5 +1,7 @@ # Strict mode to disallow ignoring returned values +_2025 February_ + This ties in to the last point. In Scheme, a non-tail expression in a body can return an arbitrary number of values, which will be silently ignored. diff --git a/notes/250210-sugar.md b/notes/250210-sugar.md index 217b0d3..a9038b6 100644 --- a/notes/250210-sugar.md +++ b/notes/250210-sugar.md @@ -1,5 +1,7 @@ # A little bit of syntax sugar never hurt anyone +_2025 February_ + ## Lambda shorthands We could benefit from a more minimal syntax to express lambda, as an diff --git a/notes/250210-symbols.md b/notes/250210-symbols.md index 280fd9f..71201a0 100644 --- a/notes/250210-symbols.md +++ b/notes/250210-symbols.md @@ -1,5 +1,7 @@ # Symbols are strings are symbols +_2025 February_ + In Scheme, symbols are literally just interned and immutable strings. They can contain any character a string can, constructed either via `string->symbol` or the modern `|foo bar baz|` syntax for quoted diff --git a/notes/250210-zero-values.md b/notes/250210-zero-values.md index 3a1eecb..7003b85 100644 --- a/notes/250210-zero-values.md +++ b/notes/250210-zero-values.md @@ -1,5 +1,7 @@ # Return zero values when there's nothing to return +_2025 February_ + This is only a minor point: It's a long-running pet peeve of mine that R5RS Scheme specifies "an diff --git a/notes/250219-format.md b/notes/250219-format.md index f757736..a7cd019 100644 --- a/notes/250219-format.md +++ b/notes/250219-format.md @@ -1,5 +1,7 @@ # I hate 'display' +_2025 February_ + WIP WIP WIP (format "template" arg ...) ;sprintf diff --git a/notes/250219-reader.md b/notes/250219-reader.md index ebbe1ea..6e604f4 100644 --- a/notes/250219-reader.md +++ b/notes/250219-reader.md @@ -1,5 +1,7 @@ # Reader? Decoder? I barely know 'er! +_2025 February_ + *This started from an expansion to the following, then became its own article:* diff --git a/notes/250228-macros.md b/notes/250228-macros.md index 3169c49..cb06e07 100644 --- a/notes/250228-macros.md +++ b/notes/250228-macros.md @@ -1,5 +1,7 @@ # Does the decoder implement macros? +_2025 February_ + I've written about the [parser/decoder dualism](reader.html) in a previous article. Long story short, the parser takes care of syntax sugar, like turning `#(...)` into `(#HASH ...)`, and the decoder takes diff --git a/notes/250228-sr.md b/notes/250228-sr.md index 0fa9e06..c7658ff 100644 --- a/notes/250228-sr.md +++ b/notes/250228-sr.md @@ -1,5 +1,7 @@ # Better syntax-rules? +_2025 February_ + Yesterday, someone on IRC asked for help in improving the following syntax-rules (s-r) macro: diff --git a/notes/250317-fastcons.md b/notes/250317-fastcons.md index 3dd4c3a..57bb6a6 100644 --- a/notes/250317-fastcons.md +++ b/notes/250317-fastcons.md @@ -1,5 +1,7 @@ # Cons cell optimization? +_2025 March_ + Assume that your Lisp implementation uses tagged pointers (possibly with NaN packing; doesn't matter), and there's enough information on pointers to tell you that the destination is the contents of a pair, diff --git a/notes/250329-boot.md b/notes/250329-boot.md index 758d264..37c3a48 100644 --- a/notes/250329-boot.md +++ b/notes/250329-boot.md @@ -1,5 +1,7 @@ # Bootstrapping Zisp +_2025 March_ + In my opinion, any serious programming language must have a serious bootstrapping strategy that addresses the "Trusting Trust" issue aka the Thompson Hack. The easiest way to do that is making sure that @@ -14,4 +16,18 @@ Zig, in turn, will *hopefully* be possible to bootstrap from C in the future, or some language implemented in C. For C, there are some ways to bootstrap it from scratch. -*** WIP *** +## Partial self-hosting + +_2025 December_ + +Currently thinking of the following strategy, which I believe is +similar to how Guile does it: + +* There will be a Zisp interpreter written in Zig, which is fairly + simple and naive in its implementation and, for example, ignores + static type declarations. It should support the full Zisp language + including hygienic macros, but be as easy as possible to maintain. + +* The Zisp compiler will be written in Zisp. The interpreter can run + the compiler (since it can run any Zisp program) and will be used to + compile the compiler. diff --git a/notes/250329-numbers.md b/notes/250329-numbers.md index 6507a67..5bbfde3 100644 --- a/notes/250329-numbers.md +++ b/notes/250329-numbers.md @@ -1,11 +1,15 @@ +# Number tower +_2025 March_ + +``` exacts: uint : 0...n sint : -n...-1 | uint - ratn : ( p: sint, q: sint ) + ratn : ( p: sint, q: uint ) comp : ( r: ratn, i: ratn ) @@ -43,3 +47,24 @@ inexact operations: double + double = double cmp128 + double = cmp128 [ cmp128 + ( r = double , i = 0 ) ] +``` + +_2025 December_ + +Mixing exact and inexact numbers implicitly should not be allowed. It +should be a type error. Conversion must be explicit. + +Basically there are two numeric towers, not one. The exact numbers +use integers all the way down; for example, an exact complex is a pair +of exact rationals which are each a pair of integers. Inexact numbers +use double, with the only other type being `complex128` which is a +pair of doubles. + +Not sure yet how exactly to deal with unsigned integers. All I know +is that I don't want there to be unsigned rational numbers; that's +just excessive. A rational number always has a signed numerator and +an unsigned denominator. + +See also: + +https://www.deinprogramm.de/sperber/papers/numerical-tower.pdf diff --git a/notes/250920-goals.md b/notes/250920-goals.md new file mode 100644 index 0000000..559609b --- /dev/null +++ b/notes/250920-goals.md @@ -0,0 +1,67 @@ +# What are the goals of Zisp? + +_2025 September_ + +Today someone asked me to elaborate on what I mean when I say I'd +really like a systems language with a garbage collector. + +Although Zisp started out with a different intention (a modern +re-invention of Scheme), I now actually want it to become that +language I'm dreaming of. + +So, there's what I mean by that: + +- Reasonably sized runtime that is (normally) dynamically linked, + comparable to say glibc + libgcc. (Not like Java, C#, Python, + Racket, etc. that need end-users to have a runtime installed that + takes dozens if not hundreds of MBs of disk space. Actually, dozens + may be necessary; see: [Using libgccjit?](libgccjit.html).) + +- Code can be compiled to provide relatively high performance. When + static types are used throughout, it should produce code whose + performance is within the same order of magnitude as C or at least + somewhat close to that. Similar to Java, Haskell, and OCaml in this + regard, if I remember their typical performance metrics correctly. + +- The GC's behaviour must be well defined, and possible to control + closely, to achieve optimal results in your program's bottlenecks. + +- As a consequence of the last two points: The number of cases you end + up wanting to "drop down to C or ASM" for performance reasons should + be minimal. Only in the most performance critical situations should + you ever need to consider adding hand written C or ASM to your + codebase, but ideally never. There may actually be a sort of low + level DSL within the language that can produce snippets of machine + code directly, so you never need to write any C, period. Hand + written platform specific ASM should only be needed in situations + you'd have needed to do the same had you been writing C. + +- It must be possible to link against dynlibs conforming to the + platform's ABI (e.g. C/C++ libs) and easily call functions from + them. It must be possible to produce such dynlibs that others can + link against and call your functions. (Not sure how to consolidate + this with GC yet.) + +- Static types are optional; the produced code falls back to using a + generic dynamic object representation if there isn't enough type + info. This dynamic object type is well defined (like a C tagged + union) as part of the language's ABI. Through this and some other + design choices, programmers would be enabled to write simple high + level "script" code when performance doesn't matter. + +- The runtime should either include a reasonably fast interpreter, so + it can offer an `eval()` function, or better yet: The compiler is + part of the runtime. Because we want to be Lispy, and allow for + rich dynamic applications like Emacs to be written in the language, + that can modify themselves at runtime. + +- The language is essentially "a Lisp" and uses a kind of s-expression + to represent code, and the parser for that format is of course part + of the runtime. Hygienic macros a la Scheme are of course part of + the language. + +Also, at this point it should be obvious that although I started this +as a little toy project, I actually dream of it becoming a serious +language project that could, one day, offer an alternative to C, C++, +Java, Python, and so on. Yes, both low-level languages with high +performance and high-level scripting languages. -- cgit v1.2.3