Skip to content

Instantly share code, notes, and snippets.

@Bike
Bike / uncalled.lisp
Created April 24, 2024 13:24
get a list of uncalled functions in package
(defun uncalled (package)
(loop for s being the present-symbols of package
for ss = `(setf ,s)
when (and (fboundp s) (not (macro-function s)) (not (special-operator-p s)) (null (ext:who-calls s)))
collect s
when (and (fboundp ss) (null (ext:who-calls ss)))
collect ss))
;; (uncalled :alexandria) => (alexandria::racons alexandria:hash-table-alist ...)
@Bike
Bike / search.lisp
Created September 28, 2023 13:28
regex-based who-whatevers search
;;; example use:
;;; (who-regex:who-calls "^MAP.*")
;;; => ((MAPCAR (SWANK::APPLICABLE-METHODS-KEYWORDS . #<SPI>)
;;; (SWANK::ENCODE-ARGLIST . #<SPI>)
;;; ...)
;;; (MAPHASH (SWANK::HASH-TABLE-TO-ALIST . #<SPI>) ...)
;;; ...)
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :cl-ppcre))
@Bike
Bike / btb.md
Last active July 31, 2023 16:43
Bytecode to BIR compiler notes

In the last couple weeks I have been writing code to compile CVM bytecode to Cleavir BIR, which can then be native compiled. The ultimate goal here is to have a two-tier compilation system: Lisp can be very rapidly compiled to bytecode, and then anything that needs to run more efficiently can be further compiled into machine code. The bytecode is pretty fast, and good enough for code that's only evaluated once or not often, so I expect that this further compilation should only be necessary for comparatively little code. This allows a separation of concerns, in that the compiler to bytecode can focus on being fast, while the compiler from bytecode can disregard compilation speed in favor of better code generation. Hypothetically, the bytecode could be used as an IR in itself, totally replacing the AST representation currently used.

In this text I'll use "bytecode compiler" to mean the compiler to bytecode, i.e. that takes Lisp source as an input and produces bytecode as output. The compiler **from

@Bike
Bike / vtest.cc
Created June 29, 2023 15:39
autovectorization test
#include <iostream>
#include <cmath>
// clang++15 vtest.cc -O2 -ffast-math -Rpass=loop-vectorize -mavx2 -o vtest
struct Stretch {
float kb;
float r0;
int I1;
int I2;
@Bike
Bike / fasl.md
Last active February 2, 2023 03:12

Introduction

I am developing this format for Clasp to replace our previous FASL formats, which are largely not under our control (e.g. they are ELF shared objects). The direct impetus is the desire to allow our Lisp VM to be targeted by cl:compile-file, but there are several broader design goals. Fundamentally, I would like to shoot for a real portable FASL format, that can be used for code interchange between different Lisp implementations running on different architectures. This is quite a ways off.

The format is vaguely based on Java classfiles, because the Java standards are some of the only standards for remotely dynamic languages I have found that are sufficiently clear, and because I think the Java "no crashing" design goal is something to aim for. The actual encoding of objects is very roughly based on conspack, which has similar speed and compactness goals as far as binary encoding goes.

Design goals

In no particular order of priority.

@Bike
Bike / thingsslimedoes.md
Last active July 28, 2022 20:38
Things slime does

quick survey of swank interfaces in order to see what could be broken out into proper portability libraries or, more optimistically, language extensions.

this is preliminary. i pretty much just went down swank.lisp looking for definterfaces. Some other portability related things are not covered yet.

Encoding/decoding

Babel

  • Encode a Lisp string to an octet vector of its UTF-8 encoding
  • Decode an octet vector of UTF-8 to a Lisp string
@Bike
Bike / hunk.md
Last active June 11, 2022 01:29
DEFSTRUCT stuff

Upgraded slot type

Implementations can store values in the slots of structure objects (and possibly standard objects) in a packed/unboxed format for space and sometimes speed efficiency, similarly to how they can be stored in arrays and complexes. But unlike those cases, there is no defined interface for the programmer to get information about this storage.

Add a function: upgraded-slot-type. This works analogously to upgraded-array-element-type or upgraded-complex-part-type, in that it takes a type specifier and environment and returns an upgraded type specifier, where the input is a recognizable (fixing the UAET spec bug) subtype of the output. There are no other requirements, and in particular implementations are permitted to always return T. upgraded-slot-type has no semantic effects and only serves as an optimization hint for the programmer.

upgraded-slot-type is essentially only relevant for structure objects. Vector and list structures have "slot types" of the vector element type a

(defmacro concatf (str &rest strings &environment env)
(multiple-value-bind (temps vals stores write read)
(get-setf-expansion str env)
`(let* (,@(mapcar #'list temps vals))
(multiple-value-bind (,@stores)
(concatenate 'string ,read ,@strings)
,write))))
@Bike
Bike / dcont.lisp
Last active July 30, 2022 16:39
delimited continuation macro transformer
(defpackage #:delimited-continuations
(:use #:cl)
(:export #:with/dc #:reset #:shift))
(in-package #:delimited-continuations)
(defmacro letcont ((&whole binding name lambda-list &body cbody) &body body)
(let ((old (gensym "OLD")))
(multiple-value-bind (cforms cdecls)
(alexandria:parse-body cbody :whole binding)

Operators that could have condition behavior more specifically defined

"Should signal an error of type-error" (or stronger?)

  1. N/A
  2. N/A
  3. compile, compiler-macro-function, macro-function, proclaim
  4. typep, type-error-datum, type-error-expected-type
  5. apply, funcall, function-lambda-expression, complement, multiple-value-call, get-setf-expansion
  6. various loop clauses?, dolist