Sign in

Vladimir Keleshev

@keleshev.com
806 followers 438 following 57 posts

OCaml programmer, author of Compiling to Assembly from Scratch: keleshev.com/cas Copenhagen

PostsRepliesMedia
Vladimir Keleshev @keleshev.com · 25/06/2026
Americans discovering vacation… Six weeks here.
000 0
Vladimir Keleshev @keleshev.com · 28/05/2026
That’s one way to spell David Raya…
000 0
Vladimir Keleshev @keleshev.com · 18/08/2025
He was no Rafael, but look at this piece, could have been a banger punk rock cover!
Onfim’s drawing of two people
020 0
Vladimir Keleshev @keleshev.com · 23/05/2025
I appreciate the idea, but the picture is good enough for me, thanks for that!
010 0
Reposted by Vladimir Keleshev
CF Bolz-Tereick @cfbolz.bsky.social · 21/05/2025
@keleshev.com not sure whether you already saw, but Compiling to Assembly from Scratch got a review in c't 9/25 (the largest German IT magazine)
151 0
Vladimir Keleshev @keleshev.com · 22/05/2025
Oh, wow! Thanks for noting!
110 0
Vladimir Keleshev @keleshev.com · 15/05/2025
Onfim was not the greatest artist, but why do you have to rub it in like that?!
A probable self portrait by Rafael, drawn when he was around the same age (1499), Ashmolean Museum, Oxford, UK.
120 0
Vladimir Keleshev @keleshev.com · 03/05/2025
Basically ‘class Parser[T]: pass’ is same as what used to be (from memory): from typing import Generic, TypeVar T = TypeVar(“T”) class Parser(Generic(T)): pass
010 0
Vladimir Keleshev @keleshev.com · 03/05/2025
Like, what language is this?
@dataclass
class Parser[T]:
    parse: Callable[[Source], ParseResult[T] | None]

    @staticmethod
    def regexp(regexp: Pattern) -> Parser[str]:
        return Parser(lambda source: source.match(regexp))

    @staticmethod
    def constant[U](value: U) -> Parser[U]:
        return Parser(lambda source: ParseResult(value, source))
010 0
Vladimir Keleshev @keleshev.com · 02/05/2025
Glad to see that Python finally got more dedicated syntax for type annotations in 3.12. Now it looks quite decent. So I updated the Python version of the book's compiler to use the new syntax: github.com/keleshev/com...
@dataclass
class Parser[T]:
    _parse: Callable[[Source], ParseResult[T] | None]

    def parse(self, s: Source) -> ParseResult[T] | None:
        return self.__dict__['_parse'](s)
    
    @staticmethod
    def regexp(regexp: Pattern) -> Parser[str]:
        return Parser(lambda source: source.match(regexp))

    @staticmethod
    def constant[U](value: U) -> Parser[U]:
        return Parser(lambda source: ParseResult(value, source))
230 0
Vladimir Keleshev @keleshev.com · 21/03/2025
I have a contrarian urge to reply "that's just easy!", which it's not; however, here's a bunch of techniques that I found very helpful: keleshev.com/advanced-err... But it relies on polymorphic variants, which is an OCaml-only feature, as far as I know.
keleshev.com
Advanced Error Handling in OCaml
030 0
Vladimir Keleshev @keleshev.com · 06/01/2025
How to reconcile that the standard says: prog [-xyz] == prog [-x] [-y] [-z] prog [options] == prog [-x] [-y] [-z] but at the same time, prog [<x> <y>] != prog [<x>] [<y>]
010 0
Vladimir Keleshev @keleshev.com · 06/01/2025
Found this counter-example from the standard: cal [[<month>] <year>] (which is clearly not the same as [<month>] [<year>]) pubs.opengroup.org/onlinepubs/9...
pubs.opengroup.org
cal
110 0
Vladimir Keleshev @keleshev.com · 04/01/2025
My only problem that makes me keep returning to this is that in EBNF the square brackets don't work this way ([<x> <y>] != [<x>] [<y>]), and the POSIX utility convention notation is clearly inspired by EBNF…
120 0
Vladimir Keleshev @keleshev.com · 04/01/2025
Then there's the `[options]` shortcut. If we assume that the `options` from the options shortcut stands for all the options in the `Options:` section, then the original behavior also makes more sense: [options] => [-x -y -z] => [-x] [-y] [-z]
110 0
Vladimir Keleshev @keleshev.com · 04/01/2025
But maybe the right way is to say that this is only the case for these short option strides, and not for anything else? [-xyz] => [-x] [-y] [-z] [-x -y -z] => [(-x -y -z)]
110 0
Vladimir Keleshev @keleshev.com · 04/01/2025
That's because the POSIX standard has examples like `prog [-xyz]` where it is clear that this means the same as `prog [-x] [-y] [-z]`.
110 0
Vladimir Keleshev @keleshev.com · 04/01/2025
In original docopt, square brackets mean each item is optional. For example, `prog [<x> <y>]` is the same as `prog [<x>] [<y>]`. Weird or not? To make both-or-nothing you need to group them like `prog [(<x> <y>)]`. You know why this was the design decision?
120 0
Vladimir Keleshev @keleshev.com · 02/01/2025
😲
010 0
Vladimir Keleshev @keleshev.com · 01/01/2025
Exactly. At my desk I have two USB-C connectors, one for Raspberry Pi, and another one for laptops, and it doesn't work if you plug in the wrong one.
000 0
Vladimir Keleshev @keleshev.com · 01/01/2025
My LG monitor (32UN880-B) is advertised at 60W PD, but at 5V it gives my Pi 400 low voltage warnings and crashes at high loads. Another BenQ monitor I have (PD3205U) advertises 90W PD and works just fine powering Pi 400.
010 0
Vladimir Keleshev @keleshev.com · 01/01/2025
Pi 5 and Pi 500 require 27W at 5V, and almost certainly no device will provide that via USB-C other than the official power supply.
210 0
Vladimir Keleshev @keleshev.com · 01/01/2025
Power new Raspberry Pis is tricky nowadays, isn't it? Pi 4 needs 15W at 5V, but normally hubs/screens/power supplies advertise their max power delivery at a higher voltage, so there's no way to know without trying.
230 0
Vladimir Keleshev @keleshev.com · 22/12/2024
Everyone know shat 3840 × 2160 divided by two gives 1920 × 1080, but did you know that 3840 × 2160 divided by *three* gives 1280 × 720! So, 720p looks crisp (but pixelated) on 4K, but horribly scaled on an 1080p panel.
010 0
Vladimir Keleshev @keleshev.com · 22/12/2024
Pinebook Pro has a 1080p panel, and downscaling looks horrible. On the other hand, Pi 400 used with 4K monitor can be downscaled, to 1080p or 720p without scaling issues.
100 0
Vladimir Keleshev @keleshev.com · 22/12/2024
Originally my plan was to get two Pinebook Pro for kids. I got one to test out, but could not get Minecraft running with a good frame rate (neither Bedrock, nor Java).
100 0
Vladimir Keleshev @keleshev.com · 22/12/2024
Of course, ever since Pi 400 came out it was obvious that there will be a Raspberry Pi laptop at some point in time, and the new Raspberry Pi screen is also an obvious stepping stone to that, but it's surprising how long it takes, considering what PINE64 folks done with Pinebook Pro long ago.
200 0
Vladimir Keleshev @keleshev.com · 22/12/2024
I remember it took me several evenings to tweak Minecraft with different plugins to get a good frame rate, but I got it working. With new Pi 500, I assume you can just use stock Minecraft Java without issues, since it performs 3x on video benchmarks.
100 0
Vladimir Keleshev @keleshev.com · 22/12/2024
I got two Pi 400 originally as Minecraft devices for kids on Christmas, but since then they are not using it much for Minecraft, more for Math Academy and school stuff. We got Nintendo Switch since then, so most gaming moved there.
Two Raspberry Pi 400 wrapped in Minecraft gift paper.
110 0
Vladimir Keleshev @keleshev.com · 22/12/2024
It's 2–3 times faster, and has a real power button, and that's the complete list of improvements. Everybody seems to be disappointed about the missing NVME slot, but I don't care much about it.
100 0
Vladimir Keleshev @keleshev.com · 22/12/2024
Not going to upgrade kids to Raspberry Pi 500 (from their Pi 400). Waiting for the next Pi X00 series for four years, of course it's a disappointment.
100 0
Vladimir Keleshev @keleshev.com · 19/12/2024
Did exactly that a few years back and after few days someone tried to use my card details to withdraw 300 bucks in Chile… 😬
000 0
Vladimir Keleshev @keleshev.com · 11/12/2024
There’s htmlact, discuss.ocaml.org/t/htmx-htmla...
discuss.ocaml.org
Htmx/htmlact web development approach
People who are looking for more lightweight alternatives – and want to do web programming without bothering too much about front end insanity can have a look at htmlact (yes indeed: sending HTML over ...
020 0
Vladimir Keleshev @keleshev.com · 05/12/2024
You don't need anybody's permission to publish, trust me!
110 0
Vladimir Keleshev @keleshev.com · 24/11/2024
Deriving json is only one opam install away in OCaml…
140 0
Vladimir Keleshev @keleshev.com · 23/11/2024
Considering the target audience is people reading paper catalogues, I think it fits.
000 0
Vladimir Keleshev @keleshev.com · 22/11/2024
Killer feature! In OCaml you would have to opam install ppx_deriving first. But I know where this is going… type classes… that’s where OCaml really lacks. But if I had (and I had) to pick type classes vs. error handling using polymorphic variants, I’d choose the latter.
2141 0
Reposted by Vladimir Keleshev
Katiuska Pino @katiuskapino.com · 22/11/2024
+600 of you are following me! It's amazing! 🌱 Let's do a little introduction. Hi! 👋 I'm Katiuska, I'm Venezuelan and I like to draw kids and sometimes write my own stories. I'm available for freelance work and also looking for representation. 🖍️ Portfolio ⭐ WIP's and Tips
091 0
Vladimir Keleshev @keleshev.com · 21/11/2024
Maybe this is helpful: github.com/keleshev/com...
github.com
compiling-to-assembly-from-scratch/contrib/ocaml at main · keleshev/compiling-to-assembly-from-scratch
Source code for the book Compiling to Assembly from Scratch https://keleshev.com/cas - keleshev/compiling-to-assembly-from-scratch
150 0
Vladimir Keleshev @keleshev.com · 20/11/2024
Totes! I usually ask myself—do people on my team know this pattern? If not, I do the long form.
030 0
Vladimir Keleshev @keleshev.com · 20/11/2024
Sure, but then those 9 lines become pages of code…
120 0
Vladimir Keleshev @keleshev.com · 20/11/2024
Yes, and the nonrec keyword is unfortunate.
110 0
Vladimir Keleshev @keleshev.com · 20/11/2024
rec is my favorite in OCaml—lets me find out that the function is recursive before reading it—super important, I think. Even better—mutually recursive functions with let rec…and—you see mutual recursion at birds eye view.
141 0
Vladimir Keleshev @keleshev.com · 20/11/2024
Excellent! Now use fold. gist.github.com/keleshev/36e...
  let size = fold ~leaf:(const 1) ~node:(+)
  let height = fold ~leaf:(const 1) ~node:(fun l r -> 1 + max l r)
  let to_string leaf = fold ~leaf ~node:(sprintf "(%s %s)")
  let reverse = fold ~leaf ~node:(fun l r -> node r l)
  let map f = fold ~leaf:(f >> leaf) ~node
  let bind f = fold ~leaf:f ~node
  let iter f = fold ~leaf:f ~node:(fun _ _ -> ())
  let for_all predicate = fold ~leaf:predicate ~node:(&&)
  let exists predicate = fold ~leaf:predicate ~node:(||)
2120 0
Vladimir Keleshev @keleshev.com · 19/11/2024
Thanks for the link!
010 0
Vladimir Keleshev @keleshev.com · 18/11/2024
Interesting, interesting…
010 0
Vladimir Keleshev @keleshev.com · 18/11/2024
I want to try out a parser design similar to angstrom, but which takes additional parameters to pass-through some "free" variables without capturing (is there a name for this pattern?). Say, three slots that can be used for anything. But then each call has those three additional parameters…
120 0
Vladimir Keleshev @keleshev.com · 18/11/2024
Especially the sequencing operator that discards the result of the first parser, like in the angstrom example above. You can pass through the success continuation to the second parser. But the success continuation to the first parser captures variables: the right parser, and the two continuations.
110 0
Vladimir Keleshev @keleshev.com · 18/11/2024
The basic sequencing operator is interesting because it is so common to sequence two parser. You got to get this right if you want non-allocation.
110 0
Vladimir Keleshev @keleshev.com · 18/11/2024
inhabitedtype/angstrom is an interesting study. It uses CPS, but non-allocation is a not a goal. Why CPS then? Here's the basic sequencing operator: github.com/inhabitedtyp...
github.com
angstrom/lib/parser.ml at 76c5ef5b0d0430eb71aa8dccad1fe23f50b96277 · inhabitedtype/angstrom
Parser combinators built for speed and memory efficiency - inhabitedtype/angstrom
220 0