summaryrefslogtreecommitdiff
path: root/notes
diff options
context:
space:
mode:
authorTaylan Kammer <taylan.kammer@gmail.com>2025-12-26 07:09:36 +0100
committerTaylan Kammer <taylan.kammer@gmail.com>2025-12-26 07:09:36 +0100
commit4210e8538e6e0adf3af7badeab33c619f3db9497 (patch)
treec7e5ae8b073eca42a2035772c7edb7a2e897308a /notes
parentf93437d8d54e26c64a88e4136e38f6a796d7fd8c (diff)
Add a note, expand other notes, add dates into notes.
Diffstat (limited to 'notes')
-rw-r--r--notes/250210-booleans.md2
-rw-r--r--notes/250210-compile.md2
-rw-r--r--notes/250210-cons.md2
-rw-r--r--notes/250210-equal.md2
-rw-r--r--notes/250210-immutable.md2
-rw-r--r--notes/250210-let.md2
-rw-r--r--notes/250210-nan.md2
-rw-r--r--notes/250210-records.md2
-rw-r--r--notes/250210-serialize.md2
-rw-r--r--notes/250210-strict-mode.md2
-rw-r--r--notes/250210-sugar.md2
-rw-r--r--notes/250210-symbols.md2
-rw-r--r--notes/250210-zero-values.md2
-rw-r--r--notes/250219-format.md2
-rw-r--r--notes/250219-reader.md2
-rw-r--r--notes/250228-macros.md2
-rw-r--r--notes/250228-sr.md2
-rw-r--r--notes/250317-fastcons.md2
-rw-r--r--notes/250329-boot.md18
-rw-r--r--notes/250329-numbers.md27
-rw-r--r--notes/250920-goals.md67
21 files changed, 146 insertions, 2 deletions
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.