Skip to content

Instantly share code, notes, and snippets.

KSSU splits timer GUI challenge

This document presents an informal “GUI framework benchmark” along the lines of [TodoMVC][]: it is a relatively simple, well-defined problem that can be used to illustrate the strengths and weaknesses of different GUI paradigms. However, unlike TodoMVC, this problem is specifically designed to stress test state management in multi-stage modal flows, where modifications to the application state can be complex but must not be committed immediately.

The problem in question is to write a speedrunning timer for [Kirby Super Star Ultra][kssu]’s [True Arena boss rush mode][kssu-true-arena]. This is a completely meaningless problem to most people, but that’s okay—this document does not assume any familiarity with KSSU or with speedrunning timers more generally. However, I do want to go over a couple basics to provide some context on the problem being solved:

  • The True Arena is a videogame boss rush mode where the objective is to beat a series of bosses as quickly as possible.
#lang hackett
(require (only-in racket/base for-syntax begin)
(for-syntax racket/base
racket/list
racket/syntax)
threading
syntax/parse/define
hackett/demo/pict
@lexi-lambda
lexi-lambda / Control.hs
Created May 14, 2017 23:01
A reimplementation of monad-control with an alternate API
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Monad.Trans.Control where
#lang curly-fn racket/base
(require (for-syntax racket/base
racket/contract
racket/function
racket/list
racket/match
racket/syntax
(only-in macrotypes/stx-utils make-variable-like-transformer)
threading)
@lexi-lambda
lexi-lambda / Main.hs
Last active July 5, 2023 18:01
Minimal Haskell implementation of Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Language.HigherRank.Main
( Expr(..)
, EVar(..)
, Type(..)
, TVar(..)
, TEVar(..)
, runInfer
) where
{-# LANGUAGE FlexibleInstances #-}
-- | An implementation of Section 3, Local Type Argument Synthesis, from the
-- paper /Local Type Inference/ by Pierce and Turner.
module Infer where
import Control.Monad (foldM, join, zipWithM)
import Data.Function (on)
import Data.List (foldl', groupBy, intercalate, intersect, nub)
#lang racket
(module combinator racket
(require (for-syntax racket/syntax
(only-in syntax/parse/private/residual this-role))
racket/dict
syntax/location
syntax/parse/define)
(provide (for-syntax wrap-expr/c expr/c))
#lang racket
(module combinator racket
(require racket/dict
syntax/location
syntax/parse/define)
(provide with-contracted-expressions)
(struct bare-string (str)
#!/usr/bin/env racket
#lang racket/base
(require racket/cmdline
racket/function
racket/match
racket/port
racket/system)
(define paths '())

Racket #langs and the REPL

The Racket platform provides a robust set of tools for developing languages, mostly centered around the macro system and the #lang protocol, which allows providing arbitrary readers to convert text input to syntax objects representing Racket modules. The REPL is a bit more complicated, however, because it has different rules—each expression needs to be dynamically read, assigned lexical context, expanded, compiled, evaluated, and printed, all in real time. (In that sense, perhaps the phrase “REPL” oversimplifies what Racket is doing, but that’s a separate conversation.)

So how does Racket accommodate this in the face of completely arbitrary user-defined languages, some of which may not even support interactive evaluation in a traditional sense? Racket mostly solves this problem by having a related but distinct set of protocols for managing runtime interactions that operates alongside #lang.

Modules and the top level

Racket’s evaluation model divides pretty much ev