a bunch of stuff sorry

This commit is contained in:
rhiannon morris 2023-12-28 01:00:25 +01:00
parent 2910daf0c6
commit 32edbb1816
33 changed files with 4874 additions and 90 deletions

View file

@ -6,17 +6,15 @@ REMOTE_DIR ?= blog
TMPDIR ?= _tmp TMPDIR ?= _tmp
BUILDDIR ?= _build BUILDDIR ?= _build
POSTSDIR ?= posts POSTSDIR ?= posts
IMAGESDIR ?= images
TEMPLATEDIR ?= templates TEMPLATEDIR ?= templates
STATICEXTS := STATICS != find $(IMAGESDIR) -type f
STATICS :=
# STATICS != parallel find $(POSTSDIR) -name '\*.{}' ::: $(STATICEXTS)
POSTS != find $(POSTSDIR) -name '*.md' POSTS != find $(POSTSDIR) -name '*.md'
OUTPUTPOSTS = \ OUTPUTPOSTS = \
$(patsubst $(POSTSDIR)/%.md,$(BUILDDIR)/%.html,$(POSTS)) \ $(patsubst $(POSTSDIR)/%.md,$(BUILDDIR)/%.html,$(POSTS)) \
$(patsubst $(POSTSDIR)/%,$(BUILDDIR)/%,$(STATICS)) \ $(addprefix $(BUILDDIR)/,$(STATICS)) \
$(BUILDDIR)/index.html $(BUILDDIR)/index.html
STYLE != find style -type f STYLE != find style -type f
@ -24,17 +22,15 @@ OUTPUTSTYLE = $(patsubst %,$(BUILDDIR)/%,$(STYLE))
OUTPUT = $(OUTPUTPOSTS) $(OUTPUTSTYLE) OUTPUT = $(OUTPUTPOSTS) $(OUTPUTSTYLE)
LANGFILTER = $(TMPDIR)/langfilter
LAANTAS_SCRIPT = $(TMPDIR)/laantas-script
ALL_TAGS = $(TMPDIR)/all-tags ALL_TAGS = $(TMPDIR)/all-tags
POST_LISTS = $(TMPDIR)/post-lists POST_LISTS = $(TMPDIR)/post-lists
NICE_DATE = $(TMPDIR)/nice-date NICE_DATE = $(TMPDIR)/nice-date
SLUG_TAGS = $(TMPDIR)/slug-tags SLUG_TAGS = $(TMPDIR)/slug-tags
EXECS = \ EXECS = \
$(LANGFILTER) $(LAANTAS_SCRIPT) \ $(LAANTAS_SCRIPT) \
$(ALL_TAGS) $(POST_LISTS) $(NICE_DATE) $(SLUG_TAGS) $(ALL_TAGS) $(POST_LISTS) $(NICE_DATE) $(SLUG_TAGS)
CABAL_FLAGS ?= -O -v0 CABAL_FLAGS ?= -O
SYNTAXDIR := syntax SYNTAXDIR := syntax
SYNTAXFILES != find $(SYNTAXDIR) -name *.xml SYNTAXFILES != find $(SYNTAXDIR) -name *.xml
@ -47,7 +43,13 @@ all: build
build: $(EXECS) $(OUTPUT) build: $(EXECS) $(OUTPUT)
POSTDEPS = $(TEMPLATEDIR)/* $(LANGFILTER) $(LAANTAS_SCRIPT) $(SYNTAXFILES) LANGFILTER != cabal list-bin langfilter
LAANTAS_SCRIPT != cabal list-bin laantas-script
POSTDEPS = \
$(TEMPLATEDIR)/* \
langfilter laantas-script \
$(SYNTAXFILES) acm.csl quox.bib
$(TMPDIR)/all-tags.md $(TMPDIR)/tags.mk &: $(POSTS) $(ALL_TAGS) $(TMPDIR)/all-tags.md $(TMPDIR)/tags.mk &: $(POSTS) $(ALL_TAGS)
@echo "[all-tags]" @echo "[all-tags]"
@ -58,6 +60,9 @@ include $(TMPDIR)/tags.mk
$(BUILDDIR)/%.html: $(POSTSDIR)/%.md $(POSTDEPS) ; $(call pandoc,post) $(BUILDDIR)/%.html: $(POSTSDIR)/%.md $(POSTDEPS) ; $(call pandoc,post)
$(BUILDDIR)/%.html: $(TMPDIR)/%.md $(POSTDEPS) ; $(call pandoc,meta) $(BUILDDIR)/%.html: $(TMPDIR)/%.md $(POSTDEPS) ; $(call pandoc,meta)
.PHONY: langfilter laantas-script
langfilter laantas-script: %: ; cabal build $@
define pandoc define pandoc
@echo "[pandoc] $<" @echo "[pandoc] $<"
mkdir -p $(dir $@) mkdir -p $(dir $@)
@ -65,17 +70,17 @@ define pandoc
LAANTAS_SCRIPT="$(LAANTAS_SCRIPT)" \ LAANTAS_SCRIPT="$(LAANTAS_SCRIPT)" \
DIRNAME="$(basename $@)" \ DIRNAME="$(basename $@)" \
FILENAME="$@" \ FILENAME="$@" \
pandoc -s --toc --template $(TEMPLATEDIR)/$(1).html -o $@ $< \ pandoc -s --toc --toc-depth=2 --template $(TEMPLATEDIR)/$(1).html -o $@ $< \
-f markdown+emoji \ -f markdown+emoji \
$(SYNTAXFLAGS) \ $(SYNTAXFLAGS) \
--filter $(LANGFILTER) --filter $(NICE_DATE) --filter $(SLUG_TAGS) \ --filter $(LANGFILTER) --filter $(NICE_DATE) --filter $(SLUG_TAGS) \
--mathjax --mathjax --citeproc --csl=apa-eu.csl
endef endef
$(BUILDDIR)/%: $(POSTSDIR)/% ; $(copy) $(BUILDDIR)/%: $(POSTSDIR)/% ; $(call copy)
$(BUILDDIR)/%: $(TMPDIR)/% ; $(copy) $(BUILDDIR)/%: $(TMPDIR)/% ; $(call copy)
$(BUILDDIR)/%: % ; $(copy) $(BUILDDIR)/%: % ; $(call copy)
define copy define copy
@echo "[copy] $<" @echo "[copy] $<"
@ -86,8 +91,6 @@ endef
BLOG_META_DEPS != find blog-meta -type f BLOG_META_DEPS != find blog-meta -type f
$(LANGFILTER): lang/langfilter/* ; $(call cabal-exe)
$(LAANTAS_SCRIPT): lang/laantas-script/* ; $(call cabal-exe)
$(ALL_TAGS): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:) $(ALL_TAGS): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:)
$(POST_LISTS): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:) $(POST_LISTS): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:)
$(NICE_DATE): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:) $(NICE_DATE): $(BLOG_META_DEPS) ; $(call cabal-exe,blog-meta:)

170
acm.csl Normal file
View file

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-US">
<info>
<title>ACM SIG Proceedings ("et al." for 15+ authors)</title>
<id>http://www.zotero.org/styles/acm-sig-proceedings-long-author-list</id>
<link href="http://www.zotero.org/styles/acm-sig-proceedings-long-author-list" rel="self"/>
<link href="http://www.acm.org/sigs/publications/proceedings-templates" rel="documentation"/>
<author>
<name>Naeem Esfahani</name>
<email>nesfaha2@gmu.edu</email>
<uri>http://mason.gmu.edu/~nesfaha2/</uri>
</author>
<contributor>
<name>Chris Horn</name>
<email>chris.horn@securedecisions.com</email>
</contributor>
<category citation-format="numeric"/>
<category field="science"/>
<category field="engineering"/>
<updated>2014-09-06T22:02:33+00:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<macro name="author">
<choose>
<if type="webpage">
<text variable="title" suffix=":"/>
</if>
<else>
<names variable="author">
<name form="long" and="text" sort-separator=", " initialize="false" delimiter-precedes-last="always" delimiter=", "/>
<label form="short" prefix=" "/>
<substitute>
<names variable="editor"/>
<names variable="translator"/>
</substitute>
</names>
</else>
</choose>
</macro>
<macro name="editor">
<names variable="editor">
<name initialize-with="." delimiter=", " and="text"/>
<label form="short" prefix=", "/>
</names>
</macro>
<citation collapse="citation-number">
<sort>
<key variable="citation-number"/>
</sort>
<layout prefix="[" suffix="]" delimiter=", ">
<text variable="citation-number"/>
</layout>
</citation>
<bibliography entry-spacing="0" second-field-align="flush" et-al-min="15" et-al-use-first="1">
<sort>
<key macro="author"/>
<key variable="title"/>
</sort>
<layout suffix=".">
<text variable="citation-number" prefix="[" suffix="] "/>
<text macro="author" suffix=", "/>
<date variable="issued" suffix=". ">
<date-part name="year"/>
</date>
<choose>
<if type="paper-conference">
<group delimiter=". ">
<text variable="title"/>
<group delimiter=" ">
<text variable="container-title" font-style="italic"/>
<group delimiter=", ">
<group delimiter=", " prefix="(" suffix=")">
<text variable="publisher-place"/>
<date variable="issued">
<date-part name="month" form="short" suffix=" "/>
<date-part name="year"/>
</date>
</group>
<text variable="page"/>
</group>
</group>
<text variable="note"/>
</group>
</if>
<else-if type="article-journal">
<group delimiter=". ">
<text variable="title"/>
<text variable="container-title" font-style="italic"/>
<group delimiter=", ">
<text variable="volume"/>
<group delimiter=" ">
<text variable="issue"/>
<date variable="issued" prefix="(" suffix=")">
<date-part name="month" form="short" suffix=" "/>
<date-part name="year"/>
</date>
</group>
<text variable="page"/>
</group>
<text variable="note"/>
</group>
</else-if>
<else-if type="patent">
<group delimiter=". ">
<text variable="title"/>
<text variable="number"/>
<date variable="issued">
<date-part name="month" form="short" suffix=" "/>
<date-part name="day" suffix=", "/>
<date-part name="year"/>
</date>
<text variable="note"/>
</group>
</else-if>
<else-if type="thesis">
<group delimiter=". ">
<text variable="title" font-style="italic"/>
<text variable="archive_location" prefix="Doctoral Thesis #"/>
<text variable="publisher"/>
<text variable="note"/>
</group>
</else-if>
<else-if type="report">
<group delimiter=". ">
<text variable="title" font-style="italic"/>
<text variable="number" prefix="Technical Report #"/>
<text variable="publisher"/>
<text variable="note"/>
</group>
</else-if>
<else-if type="webpage">
<group delimiter=". ">
<text variable="URL" font-style="italic"/>
<date variable="accessed" prefix="Accessed: ">
<date-part name="year" suffix="-"/>
<date-part name="month" form="numeric-leading-zeros" suffix="-"/>
<date-part name="day" form="numeric-leading-zeros"/>
</date>
<text variable="note"/>
</group>
</else-if>
<else-if type="chapter paper-conference" match="any">
<group delimiter=". ">
<text variable="title"/>
<text variable="container-title" font-style="italic"/>
<text macro="editor"/>
<text variable="publisher"/>
<text variable="page"/>
<text variable="note"/>
</group>
</else-if>
<else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
<group delimiter=". ">
<text variable="title" font-style="italic"/>
<text variable="publisher"/>
<text variable="note"/>
</group>
</else-if>
<else>
<group delimiter=". ">
<text variable="title"/>
<text variable="container-title" font-style="italic"/>
<text variable="publisher"/>
<text variable="note"/>
</group>
</else>
</choose>
</layout>
</bibliography>
</style>

1584
apa-eu.csl Normal file

File diff suppressed because it is too large Load diff

View file

@ -52,5 +52,6 @@ inlineText _ = Nothing
blockText :: Block -> Maybe Text blockText :: Block -> Maybe Text
blockText (Plain is) = foldMap inlineText is blockText (Plain is) = foldMap inlineText is
blockText (Para is) = foldMap inlineText is blockText (Para is) = foldMap inlineText is
--blockText Null = Just ""
blockText (RawBlock _ txt) = Just txt blockText (RawBlock _ txt) = Just txt
blockText _ = Nothing blockText _ = Nothing

View file

@ -1,7 +1,18 @@
packages: packages:
lang/**/*.cabal,
./blog-meta/blog-meta.cabal ./blog-meta/blog-meta.cabal
source-repository-package
type: git
location: https://git.rhiannon.website/rhi/lang.git
tag: 275490551bc9729003040024e8a25d16c21d90ab
subdir: langfilter
source-repository-package
type: git
location: https://git.rhiannon.website/rhi/lang.git
tag: 275490551bc9729003040024e8a25d16c21d90ab
subdir: laantas-script
source-repository-package source-repository-package
type: git type: git
location: https://git.rhiannon.website/rhi/filemanip.git location: https://git.rhiannon.website/rhi/filemanip.git
@ -12,8 +23,6 @@ source-repository-package
location: https://git.rhiannon.website/rhi/svg-builder location: https://git.rhiannon.website/rhi/svg-builder
tag: 1cbcd594d3009f9fd71f253b52ac82673bf5482e tag: 1cbcd594d3009f9fd71f253b52ac82673bf5482e
allow-newer: allow-newer: *
svg-builder:base,
svg-builder:bytestring
constraints: pandoc-types == 1.23 constraints: pandoc-types == 1.23

189
chrismas.md Normal file
View file

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html>
<meta charset=utf-8>
<link rel=stylesheet href=/style/page.css>
<title></title>
<header>
<h1>merr chrismas</h1>
<div class=meta>
<h2 class=date>monday 25 december 2023</h2>
<nav class=tags>
tags:
<ul>
<li><a href=/tag-l_ntas.html>lántas</a>
<li><a href=/tag-conlangs.html>conlangs</a>
</ul>
</nav>
</div>
<hr>
</header>
<main>
# just tell me how to say it please
sure thing. here.
```{=html}
<figure class="glosses">
```
---------------------------------------------------------------------- ----------------------------------------------------
![](chrismas/ufit_þulkussarim.svg "ufit þulkussarim"){.scr .laantas}
ufit þulkussarim
\[ˌufit ˈθuɫkɔsːɐʑɪ̃\]
ufi--t þulkus(i)--sa--ri--m
cozy--[GEN]{.abbr} midwinter--[AD]{.abbr}--[PRL]{.abbr}--[DEF]{.abbr}
(be) cozy during midwinter
---------------------------------------------------------------------- ----------------------------------------------------
```{=html}
</figure>
```
# details
now i am not a huge fan of putting christianity into my conlang, which
is hopefully understandable. but having a midwinter festival sounds
cute. the days are finally getting longer! you made it through the worst
part! and so on. so that's what this is. i think it probably takes place
the day after the solstice, but with several days of festivities, so
that there is still a little overlap with the *other* winter holiday.
it's still appropriate to say it today.
## seasons
time name pron. translation
---------- --------------------------------------------------------------- ------------------- ---------------------------------- -------------
nov--jan [![](chrismas/igisim.svg "igisim"){.scr .laantas}]{.lang} [igisim]{.lang} [\[ˈiʝɛsĩ\]]{.ipa .ipa-narrow} the freeze
feb [![](chrismas/susurum.svg "susurum"){.scr .laantas}]{.lang} [susurum]{.lang} [\[ˈsusʊrõ\]]{.ipa .ipa-narrow} the melt
mar--may [![](chrismas/šangubam.svg "šangubam"){.scr .laantas}]{.lang} [šangubam]{.lang} [\[ˈʃaŋɡɔvɑ̃\]]{.ipa .ipa-narrow} the bloom
jun--aug [![](chrismas/guwanḿ.svg "guwanḿ"){.scr .laantas}]{.lang} [guwanḿ]{.lang} [\[ˈɡɔwɑnm̩\]]{.ipa .ipa-narrow} the sun
sep--oct [![](chrismas/santum.svg "santum"){.scr .laantas}]{.lang} [santum]{.lang} [\[ˈsantõ\]]{.ipa .ipa-narrow} the rain
- in between [![](chrismas/igisim.svg "igisim"){.scr
.laantas}[igisim]{.text}]{.lang} (winter) and
[![](chrismas/šangubam.svg "šangubam"){.scr
.laantas}[šangubam]{.text}]{.lang} (spring), the month of february
is considered a transition between the two,
[![](chrismas/susurum.svg "susurum"){.scr
.laantas}[susurum]{.text}]{.lang}.
- as a result, [![](chrismas/santum.svg "santum"){.scr
.laantas}[santum]{.text}]{.lang} (autumn) is only two months long.
- [![](chrismas/šangubam.svg "šangubam"){.scr
.laantas}[šangubam]{.text}]{.lang} comes from
[![](chrismas/šani.svg "šani"){.scr .laantas}[šani]{.text}]{.lang}
(flower) and [![](chrismas/guba.svg "guba"){.scr
.laantas}[guba]{.text}]{.lang} (grow, thrive).
## putting it together
the word "midwinter", without any inflections, is
[![](chrismas/þulkusim.svg "þulkusim"){.scr
.laantas}[þulkusim]{.text}]{.lang}, which comes from
[![](chrismas/þulku.svg "þulku"){.scr .laantas}[þulku]{.text}]{.lang}
"be deep" and [![](chrismas/igisim.svg "igisim"){.scr
.laantas}[igisim]{.text}]{.lang}. unusually for lántas,
[![](chrismas/þulku.svg "þulku"){.scr .laantas}[þulku]{.text}]{.lang} is
a verb, rather than a noun. why? who knows.
```{=html}
<aside class='floating'>
```
on that page, where you see a [ƶ]{.lang}, replace it with [þ]{.lang}. i
haven't got round to updating that yet. it also has the ugly text until
i redraw [![](chrismas/č__ǧ_.svg "č ǧ"){.scr
.laantas}[č ǧ]{.text}]{.lang}, since at least if it's all ugly it's
consistent. sorry about that.
```{=html}
</aside>
```
the suffix [![](chrismas/sari.svg "sari"){.scr
.laantas}[--sari]{.text}]{.lang} is actually a pair of two suffixes,
which together mean through, or during. the details of the whole
situation are
[here](https://lang.niss.website/laantas/nouns.html#locational-cases),
but it is a cool two-dimensional system based on a thing that can be
found in some languages of the caucasus. the
[![](chrismas/m.svg "m"){.scr .laantas}[--m]{.text}]{.lang} on the end
(of all these words so far, actually) is "the". so the full form
[![](chrismas/þulkusisarim.svg "þulkusisarim"){.scr
.laantas}[þulkusisarim]{.text}]{.lang} means "during midwinter", and
that one [i]{.lang} is dropped in this phrase to give the form
[![](chrismas/þulkussarim.svg "þulkussarim"){.scr
.laantas}[þulkussarim]{.text}]{.lang}.
now, for [![](chrismas/ufit.svg "ufit"){.scr
.laantas}[ufit]{.text}]{.lang}. there is a small, but technically
non-zero, chance that you remember the word
[![](chrismas/uf_a_t.svg "uf{a}t"){.scr
.laantas}[uf`<u>`{=html}a`</u>`{=html}t]{.text}]{.lang} from
[here](https://cohost.org/niss/post/3366713-ufat-iksaha), with the
meaning of "warm". this is actually the same word, but a bit cutesy. it
means cozy.
the implied verb in this sentence is
[![](chrismas/iksaha.svg "iksaha"){.scr
.laantas}[iksaha]{.text}]{.lang}, like before. this is an auxiliary verb
for requests. for example, if [![](chrismas/šikkúha.svg "šikkúha"){.scr
.laantas}[šikkúha]{.text}]{.lang} means "you are going", then
[![](chrismas/šikkúm_iksaha.svg "šikkúm iksaha"){.scr
.laantas}[šikkúm iksaha]{.text}]{.lang} means "please go away". the
[--ha]{.lang} here means "you" (singular). here it's dropped because the
phrase is long enough already to be easily understood.
so in the end, you get
[![](chrismas/ufit_þulkussarim.svg "ufit þulkussarim"){.scr
.laantas}[ufit þulkussarim]{.text}]{.lang}, meaning "\[stay\] cozy
during the midwinter".
::: twocol-grid
![](images/crismas1.png){width="100%"}
```{=html}
<figure class="glosses left">
```
---------------------------------------------------------- ----
![](chrismas/þugusim_ai.svg "þugusim ai"){.scr .laantas}
þugusim ai
\[ˈθuɣɔsĩm‿ai\]
þugusi--m ai
miwiner--[DEF]{.abbr} be
it crismas
---------------------------------------------------------- ----
```{=html}
</figure>
```
![](images/crismas2.png){width="100%"}
```{=html}
<figure class="glosses left">
```
------------------------------------------------------------------ ----------------------------------------
![](chrismas/ufi_þugussarim.svg "ufi þugussarim"){.scr .laantas}
ufi þugussarim
\[ˌufi ˈθuɣɔsːɐʑĩ\]
ufi--(t) þugus(i)--sari--m
cozy--([GEN]{.abbr}) miwiner--[DURING]{.abbr}--[DEF]{.abbr}
merr crismas
------------------------------------------------------------------ ----------------------------------------
```{=html}
</figure>
```
:::
</main>
<footer>
<hr>
<a href=/index.html>all posts</a> ·
<a href=/all-tags.html>all tags</a>
</footer>

BIN
images/crismas1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
images/crismas2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
images/panqt.nobg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
images/panqt.nobg2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
images/panqt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
images/panqt2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

128
images/qt.svg Normal file
View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g transform="matrix(1,0,0,1,0,-589.074)">
<g id="Artboard1" transform="matrix(1,0,0,1,0,589.074)">
<rect x="0" y="0" width="512" height="512" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="0" y="0" width="512" height="512"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g id="Layer1" transform="matrix(1,0,0,1,0,-589.074)">
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z" style="fill:rgb(106,163,145);"/>
<path d="M377.884,711.693C336.293,700.43 300.054,669.785 262.138,652.082C214,629.607 164.062,622.901 104.062,671.749C67.119,701.826 49.678,732.963 42.535,761.243C30.962,807.062 46.794,846.723 58.684,868.134C43.249,895.242 17.657,946.156 11.292,987.599C6.554,1018.45 12.699,1044.84 29.913,1061.1C35.052,1065.96 41.86,1068.65 48.93,1068.63L331.972,1067.72C345.863,1067.68 357.55,1057.31 359.243,1043.52C366.154,987.234 345.224,955.205 324.246,928.746C317.981,920.843 311.7,913.643 306.933,906.122C306.893,906.06 306.854,905.998 306.815,905.936C306.815,905.936 422.605,906.387 422.605,906.387C434.897,906.435 445.736,898.338 449.176,886.536C449.176,886.536 463.389,837.158 453.114,791.761C445.218,756.873 424.397,724.288 377.884,711.693ZM370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z"/>
</g>
<g transform="matrix(0.965008,0,0,0.965008,23.2392,84.9158)">
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998L349.012,809.299Z" style="fill:rgb(234,167,208);"/>
<path d="M355.106,874.532L355.106,909.882C355.106,910.926 355.165,911.969 355.284,913.007C358.14,938.034 364.005,952.328 372.47,960.872C382.012,970.502 396.654,976.481 423.814,974.764C430.191,974.361 436.169,971.761 440.774,967.494C445.456,971.624 451.452,974.069 457.795,974.339C479.971,975.284 499.23,960.699 500.505,917.177C500.508,917.072 500.511,916.967 500.512,916.861L501.391,867.573C501.396,867.297 501.397,867.02 501.393,866.744C501.169,848.42 500.217,834.596 497.45,824.38C494.296,812.737 488.935,804.176 481.519,797.649C471.786,789.082 457.01,783.308 432.618,783.432C432.631,783.432 349.573,781.74 349.573,781.74C342.263,781.591 335.193,784.352 329.92,789.417C324.646,794.481 321.6,801.433 321.453,808.743C320.994,831.48 328.784,863.173 355.106,874.532ZM349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998L349.012,809.299Z"/>
</g>
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:rgb(200,208,208);"/>
<path d="M143.354,573.648L85.344,530.766C74.956,523.087 60.629,523.652 50.878,532.125C41.127,540.598 38.569,554.706 44.723,566.064L52.861,581.084C46.739,582.329 41.17,585.641 37.13,590.54C31.968,596.8 29.826,605.016 31.275,612.999L34.795,632.392L19.723,626.5C12.045,623.498 3.427,624.091 -3.768,628.115C-10.963,632.139 -15.979,639.172 -17.441,647.285C-22.82,677.138 -19.169,714.245 3.053,744.528C-0.524,749.897 -2.13,756.398 -1.395,762.902C1.423,787.843 15.503,804.12 39.265,813.471C55.154,819.723 76.836,822.4 102.206,822.524C128.236,822.652 221.663,850.602 221.663,850.602C230.871,853.293 240.516,850.965 247.421,845.001C264.36,853.893 280.969,863.432 285.692,866.065C306.138,877.465 321.199,860.942 321.491,860.599C326.696,854.484 330.698,848.331 333.549,842.161C333.549,842.161 424.78,866.145 424.78,866.145C434.364,868.665 444.564,865.845 451.494,858.76L465.299,844.646C469.305,840.55 471.936,835.307 472.824,829.647C472.824,829.647 478.593,791.172 470.735,761.279C465.952,743.081 456.254,727.983 441.989,719.529C417.831,705.214 418.483,707.649 362.211,689.084C359.77,688.278 358.552,685.678 356.777,683.477C353.423,679.316 350.241,674.697 346.857,670.214C338.459,659.092 328.818,649.004 316.552,642.757C316.576,642.77 291.449,628.831 291.449,628.831C291.449,628.831 212.596,533.359 212.596,533.359C204.287,523.299 190.062,520.443 178.514,526.516C159.19,536.678 145.255,553.948 143.354,573.648ZM168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z"/>
</g>
<g transform="matrix(0.708667,0.490222,-0.590127,0.85309,472.165,-35.3645)">
<path d="M288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811L288.042,686.084Z" style="fill:rgb(200,208,208);"/>
<path d="M357.816,693.781C379.27,694.41 394.552,689.435 405.628,682.19C417.919,674.15 425.773,662.686 429.231,648.687C431.083,641.196 428.812,633.409 423.039,627.451C417.266,621.494 408.593,617.988 399.388,617.89L305.247,616.889C291.685,616.745 279.598,623.972 275.457,634.701L258.647,678.255C253.855,690.669 261.039,704.094 275.344,709.457L311.957,723.184C320.451,726.369 330.222,726.195 338.544,722.712C346.867,719.229 352.849,712.81 354.824,705.244L357.816,693.781ZM288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811L288.042,686.084Z"/>
</g>
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z" style="fill:rgb(106,163,145);"/>
<clipPath id="_clip2">
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z"/>
</clipPath>
<g clip-path="url(#_clip2)">
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
<path d="M327.641,919.784C327.641,919.784 19.841,915.492 203.986,733.277L29.629,774.209L27.848,1095.35L134.952,1094.74C100.026,1000.83 183.219,931.635 183.219,931.635L327.886,932.176L327.641,919.784Z" style="fill:rgb(78,131,128);"/>
</g>
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
<path d="M199.207,978.338L194.488,978.338C187.08,978.338 181.065,984.352 181.065,991.761L181.065,1018.61C181.065,1026.02 187.08,1032.03 194.488,1032.03L196.496,1032.03C190.628,1033.37 186.245,1038.63 186.245,1044.9L186.245,1071.3C186.245,1078.59 192.16,1084.5 199.446,1084.5L408.512,1084.5C415.798,1084.5 421.713,1078.59 421.713,1071.3L421.713,1044.9C421.713,1037.62 415.798,1031.7 408.512,1031.7L375.501,1031.7C381.48,1030.34 385.949,1024.99 385.949,1018.61L385.949,991.761C385.949,984.352 379.935,978.338 372.526,978.338L348.751,978.338C353.329,976.615 356.59,972.194 356.59,967.017L356.59,942.836C356.59,936.163 351.173,930.746 344.5,930.746L213.879,941.893C207.206,941.893 191.368,936.163 191.368,942.836L191.368,967.017C191.368,972.194 194.628,976.615 199.207,978.338Z" style="fill:rgb(218,182,240);stroke:black;stroke-width:23.2px;"/>
</g>
<g>
<g transform="matrix(1.49551,0,0,0.811757,-68.9641,269.615)">
<path d="M331.231,910.593C331.231,901.292 327.133,893.74 322.084,893.74L177.219,893.74C172.17,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 172.17,961.149 177.219,961.149L322.084,961.149C327.133,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(218,182,240);"/>
</g>
<g transform="matrix(1.30126,0,0,0.825417,-41.6844,202.11)">
<path d="M331.231,910.593C331.231,901.292 326.441,893.74 320.542,893.74L178.761,893.74C172.861,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 172.861,961.149 178.761,961.149L320.542,961.149C326.441,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(229,210,240);"/>
</g>
<g transform="matrix(1.04936,0,0,0.743456,11.3293,226.044)">
<path d="M331.231,910.593C331.231,901.292 325.881,893.74 319.292,893.74L180.011,893.74C173.421,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 173.421,961.149 180.011,961.149L319.292,961.149C325.881,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(218,182,240);"/>
</g>
</g>
<path d="M168.383,626.429L68.958,552.932L76.8,603.031L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:none;stroke:black;stroke-width:24.04px;"/>
</g>
</g>
<g transform="matrix(0.965008,0,0,0.965008,23.2392,84.9158)">
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998" style="fill:rgb(234,167,208);"/>
<clipPath id="_clip3">
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998"/>
</clipPath>
<g clip-path="url(#_clip3)">
<path d="M431.785,825.472C436.196,825.531 440.671,826.375 440.658,834.109L440.018,932.263L455.298,946.8C484.319,949.064 493.525,936.796 491.605,916.37L492.484,867.082C494.969,824.742 470.519,810.706 432.434,810.998" style="fill:rgb(234,134,177);"/>
<g transform="matrix(1,0,0,1,0,-14)">
<path d="M168.383,626.429L77.248,552.932L85.09,603.031L66.687,608.077L71.417,634.14L115.716,678.848L104.584,686.03L17.977,652.172C11.345,688.979 22.041,738.658 79.821,760.458L47.756,759.807C50.925,787.849 59.682,794.751 102.342,794.96C129.994,795.095 220.32,823.237 220.32,823.237C223.592,820.023 230.65,813.419 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:none;stroke:black;stroke-width:24.04px;"/>
</g>
</g>
</g>
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:rgb(200,208,208);"/>
<clipPath id="_clip4">
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z"/>
</clipPath>
<g clip-path="url(#_clip4)">
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
<path d="M270.728,894.871L100.432,790.886C63.478,765.434 37.671,753.561 26.716,699.023L2.403,894.926L267.356,920.428L270.728,894.871Z" style="fill:rgb(172,170,169);"/>
</g>
<g transform="matrix(-1.03551,0.0394868,-0.0394868,-1.03551,497.719,1558.87)">
<path d="M163.842,871.577L126.417,815.955C118.286,808.738 60.71,796.535 46.524,779.572C21.875,750.098 39.493,711.067 37.417,693.437L-44.713,755.284L45.371,913.462L163.842,871.577Z" style="fill:rgb(172,170,169);"/>
</g>
<g transform="matrix(1.03626,0,0,1.03626,155.247,-182.181)">
<path d="M22.944,780.709L72.33,780.858L25.042,704.623L2.809,730.81L22.944,780.709Z" style="fill:rgb(172,170,169);"/>
</g>
<g transform="matrix(0.991053,-0.302738,0.302738,0.991053,-177.855,-92.9109)">
<path d="M39.909,798.246L85.999,816.588L14.692,720.663L2.809,730.81L39.909,798.246Z" style="fill:rgb(172,170,169);"/>
</g>
<g transform="matrix(0.896534,0.442974,-0.442974,0.896534,369.005,-73.9169)">
<path d="M368.002,761.693L391.151,763.055" style="fill:none;stroke:rgb(83,61,54);stroke-width:19.91px;"/>
</g>
<g transform="matrix(1.0836,0.991179,-0.64138,0.769827,186.571,-341.914)">
<path d="M351.964,770.691L376.735,752.239L387.713,766.58" style="fill:none;stroke:black;stroke-width:3.21px;"/>
</g>
</g>
</g>
<g transform="matrix(0.965008,0,0,0.965008,8.66827,66.9035)">
<ellipse cx="221.733" cy="727.732" rx="38.255" ry="46.49" style="fill:rgb(251,248,235);"/>
<clipPath id="_clip5">
<ellipse cx="221.733" cy="727.732" rx="38.255" ry="46.49"/>
</clipPath>
<g clip-path="url(#_clip5)">
<g transform="matrix(1.90259,0,0,1.40285,-162.229,-333.591)">
<ellipse cx="203.804" cy="757.093" rx="25.898" ry="33.515" style="fill:rgb(251,248,235);"/>
</g>
<g transform="matrix(1.90259,0,0,1.40285,-192.925,-329.328)">
<ellipse cx="203.804" cy="757.093" rx="25.898" ry="33.515" style="fill:rgb(127,66,180);"/>
</g>
<g transform="matrix(1,0,0,1.1684,1.99638,-148.036)">
<rect x="170.37" y="672.129" width="113.591" height="70.11" style="fill:rgb(78,131,128);"/>
<clipPath id="_clip6">
<rect x="170.37" y="672.129" width="113.591" height="70.11"/>
</clipPath>
<g clip-path="url(#_clip6)">
<g transform="matrix(1.03626,0,0,0.886908,-15.273,46.6391)">
<circle cx="228.602" cy="798.456" r="38.625" style="fill:rgb(106,163,145);"/>
</g>
</g>
</g>
</g>
<path d="M221.733,669.221C194.68,669.221 171.458,694.855 171.458,727.732C171.458,760.609 194.68,786.243 221.733,786.243C248.787,786.243 272.009,760.609 272.009,727.732C272.009,694.855 248.787,669.221 221.733,669.221ZM221.733,681.242C242.847,681.242 259.988,702.074 259.988,727.732C259.988,753.391 242.847,774.223 221.733,774.223C200.62,774.223 183.479,753.391 183.479,727.732C183.479,702.074 200.62,681.242 221.733,681.242Z"/>
</g>
<g transform="matrix(0.708667,0.490222,-0.590127,0.85309,472.165,-35.3645)">
<path d="M288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811" style="fill:rgb(200,208,208);"/>
</g>
<g transform="matrix(1,0,0,1,9,9)">
<path d="M280.43,915.61C252.675,916.872 236.398,922.853 201.061,922.853L183.825,922.757C171.311,921.177 163.129,919.303 151.665,907.851" style="fill:none;stroke:black;stroke-width:11.6px;"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/quox-tod.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

BIN
images/quox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

1
lang

@ -1 +0,0 @@
Subproject commit f6d10672d2c621a9b812142289124e72b869d265

View file

@ -0,0 +1,315 @@
---
title: intro to quox
date: 2023-06-05
tags: [computer, quox (language)]
show-toc: true
bibliography: quox.bib
link-citations: true
...
<figure class='shaped floating' style='shape-outside: url(/images/quox.png)'
aria-label=''>
<img src=/images/quox.png
alt='quox sprite from quest of ki'
title='quox sprite from quest of ki'>
<figcaption>(this is a quox)</figcaption>
</figure>
hello for _a while_ now i've been working on a language called quox. the
one-sentence, meaningless summary is "qtt and xtt mashed together".
:::aside
wow, q and x! what an amazing coincidence!
:::
but maybe i should say what those are. i'm going to _try_ to aim this at someone
who knows normal languages. i guess we'll see how successful that is. so first,
# dependent types {#dt}
maybe you already know this one. skip it if you want. (maybe you know all of
this but you came to say hi anyway. hi!)
all a <dfn>dependent type</dfn> is is a type that is allowed to talk about run
time values. like a dependent pair might be `(len : ) × Array len String` for
a length paired with an array of strings with that length. a dependent function
with a type like `(len : ) → (x : A) → Array len A` takes a length and element
`x` as arguments, and returns an array of that many copies of `x`.
even ~~parametric polymorphism~~ generics are a specific form of dependent type:
you take a type as a parameter, and get to use it in the types of the other
arguments.
:::aside
<details>
<summary>but i can do that in rust/c++/haskell too</summary>
yeah! well, partially. in rust you can have like
```rust
fn replicate<const N: usize, A: Clone>(val: A) -> [A; N] {
[(); N].map(|_| val.clone())
}
```
but it's a bit more restricted:
- `N` has to always be known at compile time. you can't, for example, have the
length come from a config file or command-line argument
- in rust [(at the time of writing)]{.note} and c++, only certain number-ish
types can be used in this way. in ghc-haskell you have more choice for what
data can be used in types, but you—or template haskell—have to rewrite
functions for the type and value level, and have "singleton" types to bridge
between compile time and run time
so yeah, you can get some of the way there, but not completely.
</details>
:::
dependent types let you classify values more precisely than before, so you can
do things like have ASTs that reflect their local variables in the type.
in quox, and most uses of this technique, it's enough to just keep the _number_
of variables in scope.
[(there are two counts in quox; see [below](#xtt) for why.)]{.note}
in a definition like
<!-- i need a default quantity so i can write this without any "what's that" -->
```quox
def backwards-plus : ω. → ω. =
λ a b ⇒ plus b a
```
:::aside
<details>
<summary>what does all that mean</summary>
- the `ω` before each argument means you have no restrictions on how you can
use it. see [below](#qtt). i want to have a default so you could just write
``, but i can't decide what the default should _be_
- functions are curried, which means they take their arguments one by one, like
in haskell or ocaml, rather than in a tuple. doing it this way makes writing
dependencies (and quantities) easier.
- a function is written as `λ var1 var2 ⇒ body`
- all those funky symbols have ascii alternatives, so you if you like it better
you can also write
```quox
def backwards-plus : #.Nat -> #.Nat -> Nat =
fun a b => plus b a
```
</details>
:::
the right hand side `λ a b ⇒ plus b a` is necessarily a `Term 0 0`, with
no local variables. the body of the function is a `Term 0 2`, because it has two
term variables in scope.
typing contexts also know how many variables they bind, so you can know for sure
you are keeping the context properly in sync with the term under consideration.
and if you forget, then the compiler, uh, "reminds" you. since it's notoriously
easy to make off-by-one errors and similar mistakes when dealing with variables,
so having the computer check your work helps a lot.
--------------------------------------------------------------------------------
you might not want to have every property you will ever care about be always
reflected in types. quox's expressions have their scope size in their type,
because dealing with variables is ubiquitous and fiddly, but they don't have
like, a flag for whether they're reducible. i _do_ care about that sometimes,
but it's easier to have it as a separate value:
```idris
-- in Data.So in the standard library
data Oh : Bool -> Type where
Oh : So True
-- in Data.DPair (simplified for now)
data Subset : (a : Type) -> (p : a -> Type) -> Type where
Element : (x : a) -> p x -> Subset a p
isRedex : Definitions -> Term d n -> Bool
whnf : (defs : Definitions) -> WhnfContext d n ->
Term d n -> Subset (Term d n) (\t => So (not (isRedex defs t)))
```
a term is a <dfn>redex</dfn> (reducible expression) if the top level AST node is
something that can be immediately reduced, like a function being applied to an
argument, or a definition that can be unfolded. <dfn>whnf</dfn> ([weak head
normal form][whnf]) reduces the top of the expression until there are no more
reductions to do, and then returns the result, along with a proof that there are
no more.
[whnf]: https://en.wikipedia.org/wiki/Lambda_calculus_definition#Weak_head_normal_form
datatype arguments can be of any type, but also, data constructors can restrict
the values of those arguments in their return types. (this is what makes them
useful in the first place.) in this case, `So` only has one constructor, only
usable when its argument is `True`, meaning that constructing a value of type
`So p` is only possible if the expression `p` reduces to `True`.
:::aside
<details>
<summary>`So` considered harmful, or whatever</summary>
in a lot of cases you need to write the property inductively, i.e., as a
datatype, like
```idris
data NotRedex : Definitions -> Term d n -> Type
-- DPair is similar to Subset
whnf : (defs : Definitions) -> WhnfContext d n ->
Term d n -> DPair (Term d n) (\t => NotRedex defs t)
```
the reason for this is that it is often easier to define other functions by
matching on the proof rather than the original term.
but in this case that is not necessary and writing a function into `Bool` is
easier.
</details>
:::
other parts of the compiler, like equality checking, can similarly require
a proof that their arguments are not redexes, so that they don't have to keep
calling `whnf` over and over, or risk wrongly failing if one argument isn't
reduced enough.
# qtt (quantitative type theory) {#qtt}
:::note
(idris (2) has this one too, so i can still use real examples for now)
:::
having this extra safety is nice, but it would be even nicer if it we could be
sure it wouldn't affect run time efficiency. for a long time, dependently typed
languages have tried to use heuristics to elide constructor fields that were
already determined by other fields, at least as far back as 2003 [@indices].
but these analyses are anti-modular, in that a constructor field can only be
erased if it is not matched against _anywhere_ in the whole program.
maybe we should try telling the computer what we actually want.
in qtt [@qtt; @nuttin], every local variable is annotated with
a <dfn>quantity</dfn>, telling us how many times we can use it at run time. in
quox [(and idris2)]{.note}, the possible choices are `0` (not at all;
<dfn>erased</dfn>), `1` (exactly once; <dfn>linear</dfn>), and `ω` (any number
of times; <dfn>unrestricted</dfn>, and the default in idris and not written). if
a variable is marked with `0`, then you can't do anything with it that would
affect run time behaviour. for example,
- you can only match on values if their type has one or zero cases. if you
"have" a variable of the empty type `v : {}`, you're already in an unreachable
branch, so it's fine to abort with
`case0 v return 〈whatever〉 of { }`.
if you have an erased pair, it's fine to split it up, but the two parts will
still be erased.
matching on something like `Bool` isn't possible, because the value is no
longer there to look at.
- type signatures only exist at compile time so you can do whatever you want
there.
- equality proofs don't have any computational behaviour (unlike in [some other
type theories][hott]), so [coercion](#xtt) works with an erased proof
[hott]: https://homotopytypetheory.org
as well as erasure, there is also linearity. a linear variable must be used
exactly once in a linear context (and any number of times in an erased context,
like in types or proofs talking about it). this is useful for things like file
handles and other kinds of resources that have strict usage requirements. it's
similar to passing a variable by value in rust, where after you do so, you can't
use it yourself any more.
:::aside
there's no equivalent to <dfn>borrowing</dfn> inside the type system, but
i think with a careful choice of builtins, it would be possible to do a similar
thing in an external library.
_[rust person voice]_ it would be less _ergonomic_ as library, but having
a borrow checker inside the language would immediately blow my _complexity
budget_. :crab:
:::
i don't have much to say about this, honestly, but ask any rust user about the
benefits of tracking resource ownership in types.
--------------------------------------------------------------------------------
so where do these quantities come from? from the types, of course. a function
type in quox, which looks like `ρ.(x : A) → B`, has a quantity ρ attached,
which describes how a function value of that type can use its argument.
an identity function `λ x ⇒ x` can have type `1.A → A` or `ω.A → A`, but not
`0.A → A`. and a "diagonal" function `λ x ⇒ (x, x)` can only be `ω.A → A × A`.
a whole definition can be erased (and if it's a definition of a type, it has to
be, since types don't exist at run time), like
```quox
def0 TwoOfThem : ★ = ×
```
finally, you can mark a specific term with a quantity. say you want to write
a function that returns some number, plus an erased proof that it's even.
obviously you can't mark the whole definition as erased with `def0`, since
you want the number itself. and giving the return type as `(n : ) × Even n`
makes the proof appear at run time, which might be unwanted if it's something
big. so you can erase the second half of the pair by writing
`(n : ) × [0. Even n]`. a value of a "boxed" type `\[π. A]` is written `\[e]`
if `e : A`. for a slightly bigger example, you might want a decidable equality
that gives you _erased_ proofs, so you can use them in coercions, but they don't
show up at run time.
```quox
def0 Not : ω.★ → ★ = λ A ⇒ ω.A → {}
def0 Either : ω.★ → ω.★ → ★ = ⋯ -- constructors Left and Right
def0 Dec : ω.★ → ★ = λ A ⇒ Either [0. A] [0. Not A]
def Yes : 0.(A : ★) → 0.A → Dec A = λ A y ⇒ Left [0. A] [0. Not A] [y]
def No : 0.(A : ★) → 0.(Not A) → Dec A = λ A n ⇒ Right [0. A] [0. Not A] [n]
def0 DecEq : ω.★ → ★ = λ A ⇒ ω.(x y : A) → Dec (x ≡ y : A)
```
you can also use the same construction to have some unrestricted parts of an
otherwise linear structure.
:::aside
still missing from this story, in my opinion, is some form of compile-time
irrelevance. a lot of the time, you don't care about the content of a proof,
only that it is satisfied, so if division has a type like
`div : 1.ℚ → 1.(d : ) → 0.(NonZero d) → ℚ`, you want some way to get
`div x y p₁` and `div x y p₂` to always be equal, without even having to look at
`p₁` and `p₂`. there's no way to do that yet, because it doesn't seem to fit
into qtt cleanly. maybe a single squash type..?
:::
# xtt ("extensional" type theory) {#xtt}
:::aside
but not _that_ extensional type theory
:::
[@xtt]
# other stuff {#misc}
- crude but effective [@crude; @mugen]
- bidirectional typechecking [@bidi]
- ...
# i still don't know how to actually write a program {.unnumbered}
i know. that's ok. i'm just trying to communicate why someone might,
hypothetically, care.
did it work?
# references {#ref}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
---
title: quox. the language
date: 2023-10-25
tags: [quox, computer, types]
bibliography: quox.bib
link-citations: true
show-toc: true
...
<style>
header h1 { margin-left: 0; }
header h1::before, header h1::after {
content: url(../images/qt.svg);
display: inline-block;
height: 0.75em; width: 0.75em;
padding: 0 0.5em;
}
header h1::before {
transform: rotateY(0.5turn);
}
main > :is(h1, h2, h3, h4, h5, h6)::after {
content: url(../images/quox-tod.png);
image-rendering: crisp-edges;
image-rendering: pixelated;
margin-left: 0.5em;
}
.qtt-q { font-family: Muller; font-weight: 600; color: #60c; }
.xtt-x { font-family: Muller; font-weight: 600; color: #082; }
#panqt {
--width: 202px; --height: 200px;
}
#panqt div {
width: var(--width); height: var(--height);
position: relative;
}
#panqt img, #panqt div::before {
position: absolute;
top: 0; left: 0;
width: var(--width); height: var(--height);
}
#panqt div::before {
content:
image-set(url(../images/panqt.png) 1x,
url(../images/panqt2x.png) 2x);
mix-blend-mode: multiply;
}
#panqt figcaption {
width: var(--width);
}
</style>
:::{.aside .floating}
### [hot minute][wkt]&ensp;*n.* {.unnumbered}
1. A long period of time.
2. A short period of time.
3. An unspecified period of time.
[wkt]: https://en.wiktionary.org/wiki/hot_minute
:::
for the last _hot minute_ [@hotminute], ive been working on a little programming language. its finally starting to approach a state where it can compile some programs, so maybe i should talk about it a bit.
# what is a quox [(tl;dr for type system nerds)]{.note}
<figure class=floating>
<img src=../images/quox.png class='shadow pixel'
alt='a dragon from an old arcade game'
title='use my warps to skip some floors!'>
<figcaption>this is also a quox.</figcaption>
</figure>
0. its a *dependently typed functional language*, like your agdas and your idrises.
1. *[q]{.qtt-q}uantitative type theory* (qtt) [@nuttin; @qtt] is a nice combination of dependent types, resource tracking, and erasure of stuff like proofs.
2. it uses *[x]{.xtt-x}tt* [@xtt] for equality. i think it's neat
3. it has a *closed type universe*. you dont define new datatypes, but the language gives you building blocks to put them together. this is because of xtt originally, but i just ran with it.
so now you can see where the name [q]{.qtt-q}uo[x]{.xtt-x} comes from. other than my favourite dragon. anyway it also has
4. *bidirectional type checking* [@bidi]
5. crude-but-effective stratification [@crude; @crude-blog] for dealing with universes
# dependent types
<figure class=floating>
<div><img src=../images/panqt.png srcset='../images/panqt.png 2x'
width=202 height=200
alt='one of my fursonas is a quox with three heads'
title='i hear putting pictures of your fursona on your blog is a good way to get hacker news types Big Mad'></div>
<figcaption>
sometimes i am also a quox. or three, depending on how you count.
</figcaption>
</figure>
there are lots of languages with dependent types already. if you are reading this, chances are probably _quite_ high you already know what they are and can skip to the next section.
`*but still something. probably*`
# qtt
sometimes, values can only be used in certain ways to make sense. this isn't controversial: it's the old use-after-free.
# xtt
# references {#refs}

View file

@ -0,0 +1,177 @@
---
title: quox. the language
date: 2023-10-25
tags: [quox, computer, types]
bibliography: quox.bib
link-citations: true
show-toc: true
...
<style>
header h1 { margin-left: 0; }
header h1::before, header h1::after {
content: url(../images/qt.svg);
display: inline-block;
height: 0.75em; width: 0.75em;
padding: 0 0.5em;
}
header h1::before {
transform: rotateY(0.5turn);
}
main > :is(h1, h2, h3, h4, h5, h6)::after {
content: url(../images/quox-tod.png);
image-rendering: crisp-edges;
image-rendering: pixelated;
margin-left: 0.5em;
}
.qtt-q { font-family: Muller; font-weight: 600; color: #60c; }
.xtt-x { font-family: Muller; font-weight: 600; color: #082; }
#panqt {
--width: 202px; --height: 200px;
}
#panqt div {
width: var(--width); height: var(--height);
position: relative;
}
#panqt img, #panqt div::before {
position: absolute;
top: 0; left: 0;
width: var(--width); height: var(--height);
}
#panqt div::before {
content:
image-set(url(../images/panqt.png) 1x,
url(../images/panqt2x.png) 2x);
mix-blend-mode: multiply;
}
#panqt figcaption {
width: var(--width);
}
</style>
:::{.aside .floating}
### [hot minute](https://en.wiktionary.org/wiki/hot_minute)&ensp;<i>n.</i> {.unnumbered}
1. A long period of time.
2. A short period of time.
3. An unspecified period of time.
:::
for the last _hot minute_ [@hotminute], ive been working on a little programming language. its finally starting to approach a state where it can compile some programs, so maybe i should talk about it a bit.
# what is a quox [(tl;dr for type system nerds)]{.note}
<figure class=floating>
<img src=../images/quox.png class='shadow pixel'
alt='a dragon from an old arcade game'
title='use my warps to skip some floors!'>
<figcaption>this is also a quox.</figcaption>
</figure>
0. its a *dependently typed functional language*, like your agdas and your idrises.
1. it has a *closed type universe*. you dont define new datatypes, but the language gives you building blocks to put them together.
2. *[q]{.qtt-q}uantitative type theory* (qtt) [@nuttin; @qtt] is a nice combination of dependent types, resource tracking, and erasure of stuff like proofs.
3. *[x]{.xtt-x}tt* [@xtt], which `*i sure hope i remember to come back and add this!*`
- the closed type universe is a consequence of xtt (as well as its kinda-predecessor ott [@ott-now]), but i decided to just run with it.
- “xtt” stands for “extensional type theory”, but its not _that_ extensional type theory. i know. not my fault.
so now you can see where the name [q]{.qtt-q}uo[x]{.xtt-x} comes from. other than my favourite dragon. anyway it also has
<figure class=floating id=panqt>
<div><img src=../images/panqt.nobg.png srcset='../images/panqt.nobg2x.png 2x'
width=202 height=200
alt='one of my fursonas is a quox with three heads'
title='i hear putting pictures of your fursona on your blog is a good way to get hacker news types Big Mad if they find out about it'></div>
<figcaption>
sometimes i am also a quox. or three, depending on how you count.
</figcaption>
</figure>
4. *bidirectional type checking* [@bidi] `*this one too*`
5. crude-but-effective stratification [@crude; @crude-blog] for dealing with universes. `*does this need more detail too?*`
6. *written in idris2*. that doesnt really have much impact on the language itself, other than the compilation process, but im enjoying using a dependently typed language for something substantial. even if its one youre not currently supposed to be using for anything substantial. also currently it spits out scheme, like idris, because that was easy.
7. all the non-ascii syntax is [optional], but i like it.
[optional]: https://git.rhiannon.website/rhi/quox/wiki/ascii-syntax
as for what it _doesnt_ have: any but the most basic of conveniences. sorry.
# dependent types
there are lots of languages with dependent types—well, quite a few—so i wont spend too much time on this.
`*but still something*`
# closed type universe
instead of having datatypes like in normal languages, in quox you get the basic building blocks to make them. the main building blocks are functions, pairs, enumerations, equality types, strings, and natural numbers. some sort of syntactic sugar to expand a datatype declaration into this representation _is_ something i want to add, but it'd be in the pretty distant future.
:::aside
_at the moment_, natural numbers are the only recursion possible. so you can define types with the same recursive structure, like lists, but binary trees and stuff are not _currently_ possible, until i replace them with something more general. probably w-types [@nlab-wtype].
:::
but right now you can define a few types like this. see [qtt](#qtt) below for what all the `0`s and `ω`s mean. due to the lack of generic recursion, but the presence of _natural numbers_ specifically, a list is a length, followed by a nested tuple of that length (terminated by `'nil`).
```quox
def0 Vec : → ★ → ★ =
λ n A ⇒
case n return ★ of {
zero ⇒ {nil};
succ p, As ⇒ A × As
} -- ↖ As = Vec p A
def0 List : ★ → ★ = λ A ⇒ (n : ) × Vec n A
def Nil : 0.(A : ★) → List A = λ A ⇒ (0, 'nil)
def Cons : 0.(A : ★) → A → List A → List A =
λ A x xs ⇒ case xs return List A of { (len, xs) ⇒ (succ len, x, xs) }
def NilS = Nil String
def ConsS = Cons String
def example = ConsS "im" (ConsS "gay" NilS)
def0 example-eq : example ≡ (2, "im", "gay", 'nil) : List String =
refl (List String) example
```
you might have noticed that i didn't write the eliminator. that is because they are kind of ugly. if you want to see it anyway you can find it in [the example folder][ex].
[ex]: https://git.rhiannon.website/rhi/quox/src/commit/246d80eea2/examples/list.quox#L12-L25
# qtt
sometimes, values of some type can only be used in certain ways to make sense. this is hardly controversial; if you do this with
a problem that dependent types used to have a lot is that the blurring of compile-time and run-time data can lead to more being retained than necessary.
`*is there an example that has superlinear junk data without resorting to peano naturals or some shit*`
consider this vector (length-indexed list) definition from a _hypothetical language_ with normal inductive types.
```agda
data Vect (A : ★) : → ★ where
[] : Vect A 0
_∷_ : (n : ) → A → Vect A n → Vect A (succ n)
```
in a totally naive implementation, `cons` would store `n`, the length of its tail (and maybe even some kind of representation of `A` too). so a three element list would look something like
# xtt
`*mention about type-case and the closed universe*`
# bidirectional type checking
# references {#refs}

View file

@ -0,0 +1,513 @@
---
title: quox's type system
tags: [quox, programming]
date: 2021-07-26
...
main inspirations:
- [quantitative type theory](https://bentnib.org/quantitative-type-theory.pdf)
(2018\)
- mostly [conor's version](
https://personal.cis.strath.ac.uk/conor.mcbride/PlentyO-CR.pdf),
even though it's older (2016)
- track how often things are used in terms. you get linearity if you want
it, but also, predictable erasure
- [graded modal dependent type theory](https://arxiv.org/pdf/2010.13163) (2021)
- a refinement of qtt. track occurrences in types too! your context becomes
two-dimensional but that's ok
- also the way quantities are tracked is a bit different
- [observational type theory](
https://www.cs.nott.ac.uk/~psztxa/publ/obseqnow.pdf) (2007)
- nice middle ground between intensional and extensional type theory. you
get stuff like funext in a decidable setting
- [xtt](https://arxiv.org/pdf/1904.08562.pdf)
("extensional" type theory, but not that one) (2019)
- a cubical reformulation of the ideas in ott. no univalence stuff tho,
don't worry i'm still #&#x2060;UIP&#x2060;Crew
<!-- those are WORD JOINERs btw, so that hopefully a screen reader will know to
say "hash u.i.p. crew" instead of whatever else -->
the basic idea is to mash all of these things together, obviously, but also to
embrace a closed type theory, so that stuff like the type-case in xtt can make
sense, and try to be a nice language anyway. what's a datatype?
the core then only needs to know about basic type formers like functions,
pairs, w-types (:cold_sweat:), cubes (:cold_sweat: :cold_sweat: :cold_sweat:),
etc, and their eliminators, instead of having to do the whole thing with
datatypes and functions. those would still exist in an eventual surface
language tho, since otherwise writing anything will be extremely painful, but
elaborated to this stuff.
# syntax
:::defs
$$
\newcommand\EQ{\mathrel\Coloneqq}
\newcommand\OR[1][]{\mkern17mu #1| \mkern10mu}
\newcommand\Or{\mathrel|}
\newcommand\KW\mathsf
\newcommand\L\mathbfsf
$$
$$
\newcommand\Type[1]{\KW{type}_{#1}}
\newcommand\Tup[1]{\langle #1 \rangle}
\newcommand\WTy{\mathbin\blacktriangleleft}
\newcommand\WTm{\mathbin\vartriangleleft}
\newcommand\BoxType{\mathop\blacksquare}
\newcommand\BoxTy[1]{\mathop{\blacksquare_{#1}}}
\newcommand\BoxTm{\mathop\square}
\newcommand\Case{\KW{case}\:}
\newcommand\Of{\:\KW{of}\:}
\newcommand\Return{\:\KW{return}\:}
\newcommand\Rec{\KW{rec}\:}
\newcommand\With{\:\KW{with}\:}
\newcommand\Arr{\mathrel\mapsto}
\newcommand\TCArr{\mkern-10mu \Arr}
\newcommand\Coe{\KW{coe}\:}
\newcommand\Comp{\KW{comp}\:}
\newcommand\Qty{\mathrel\diamond}
$$
:::
bidirectional syntax. i like it.
$$
\begin{align*}
x,y,z,X,Y,Z &\EQ \dotsb & \text{term variables} \\
\iota &\EQ \dotsb & \text{dimension variables} \\
\ell &\EQ n & \text{universe levels ($n \in \mathbb{N}$)} \\
\L{a},\L{b},\L{c}, \text{etc} &\EQ \dotsb & \text{symbols} \\[.75em]
%
\pi,\rho,\phi,\sigma &\EQ 0 \Or 1 \Or \omega
& \text{quantities} \\[.75em]
%
q,r &\EQ \varepsilon \Or \iota & \text{dimensions} \\
\varepsilon &\EQ 0 \Or 1 & \text{dimension endpoints} \\[.75em]
%
s,t,A,B &\EQ \Type\ell & \text{types \& terms: universe} \\
&\OR (x \Qty \pi,\rho : A) \to B \Or \lambda x. t
& \text{functions} \\
&\OR (x \Qty \rho : A) \times B \Or \Tup{s, t}
& \text{pairs} \\
&\OR (x \Qty \rho,\phi : A) \WTy B \Or s \WTm t
& \text{inductive data} \\
&\OR \{ \overline{\L{a}_i}^i \} \Or \L{a}
& \text{enumerations} \\
&\OR \BoxTy\pi A \Or \BoxTm s
& \text{quantity} \\
&\OR s =_{\iota.A} t \Or \lambda\iota.s
& \text{equalities} \\
&\OR \underline{e}
& \text{elimination in term} \\[.75em]
%
e, f &\EQ x & \text{eliminations: variable} \\
&\OR f \: s
& \text{application} \\
&\OR \Case e \Return z. A \Of \Tup{x, y} \Arr s
& \text{unpairing} \\
&\OR \Rec e \Return z. A \With s
& \text{recursion} \\
&\OR \Case e \Return z. A \Of
\{ \overline{\L{a}_i \Arr s_i}^i \}
& \text{enumeration} \\
&\OR \Case e \Return z. A \Of \BoxTm x \Arr s
& \text{quantity} \\
&\OR f \: q
& \text{equality application} \\
&\OR \Coe (\iota.A)^q_{q'} \: s
& \text{coercion} \\
&\OR[\left] \Comp A^q_{q'} \: s \:
\left\{
\begin{aligned}
(r=0) & \Arr \iota.t_0 \\
(r=1) & \Arr \iota.t_1
\end{aligned}
\right\} \right.
& \text{composition} \\
&\OR[\left] \Case e \Return A \Of
\left\{
\begin{array}{ll}
\Type{} & \TCArr t_0 \\
\Pi \: X \: Y & \TCArr t_1 \\
\Sigma \: X \: Y & \TCArr t_2 \\
\KW{W} \: X \: Y & \TCArr t_3 \\
\KW{Enum} & \TCArr t_4 \\
\BoxType X & \TCArr t_5 \\
\KW{Eq} \: X \: X' \: y \: z \: z' & \TCArr t_6 \\
\end{array}
\right\} \right.
& \text{type case} \\
&\OR s : A
& \text{annotation}
\end{align*}
$$
__TODO wtf does all this cube stuff even mean. especially composition__
i'm going to use abbreviations like $A \to_\pi B$ for $(x \Qty \pi,0 : A) \to
B$, just $A$ for $z. A$ or $\iota. A$ in elim return types, etc for
non-dependent stuff. $\emptyset$ means $\{\,\}$.
a function type has two quantities attached to it, since unlike in qtt classique
we care about what's going on in types too. in $(x \Qty \pi,\rho : A) \to B$,
$x$ is used $\pi$ times in the body of a function of this type, and it's used
$\rho$ times in $B$ itself.
pairs $(x \Qty \rho : A) \times B$ only have one since it's just two things, the
first doesn't occur in the second at all, but we still care about what's going
on in $B$
w-types $(x \Qty \rho,\phi : A) \WTy B$ also have two quantities, but in
a different way. the $\rho$ still says how $x$ is used in $B$, but this time
$\phi$ says how $x$ is used in $t$ in a term like $s \WTm \lambda x. t$.
## examples of encodings
also possible syntax. TODO universe & quantity polymorphism obviously
```
-- empty type
Void : type 0 := {};
absurd : (A @ 0,1 : type 0) -> Void @ 1 -> A :=
fun A v => case v return A of {};
-- unit type
Unit : type 0 := {'tt};
swallow : (A @ 0,2 : type 0) -> Unit @ 1 -> A -> A :=
fun t x => case t return A of {'tt => x};
-- boolean type
Bool : type 0 := {'false; 'true};
-- use 'case' for 'if'
not : Bool @ 1 -> Bool :=
fun b => case b return Bool of {'false => 'true; 'true => 'false};
-- natural numbers
NatTag : type 0 := {'zero; 'suc};
NatBody : NatTag @ 1 -> type 0 :=
fun n => case n return type 0 of {'zero => Void; 'suc => Unit};
Nat : type 0 := (tag : NatTag @ 1,1) <|| NatBody tag;
zero : Nat := 'zero <| absurd;
suc : Nat @ 1 -> Nat := fun n => 'suc <| fun t => swallow t n;
elimNat : (P @ inf,0 : Nat @ inf -> type 0) ->
(Z @ inf,0 : P zero) ->
(S @ inf,0 : (n @ 1,2 : Nat) -> P n -> P (suc n)) ->
(n @ inf,1 : Nat) -> P n :=
fun P Z S n =>
rec n return n₀. P n₀ with fun tag =>
case tag
return t. (f @ inf,2 : NatBody t @ 0 -> Nat) ->
(IH @ inf,0 : (b @ 1 : NatBody t) -> P (f b)) ->
P (t <| f)
of {'zero => fun _ _ => Z;
'suc => fun f IH => S (f 'tt) (IH 'tt)}
```
or something.&#x3000;:ghost: eliminators :ghost: w-types :ghost: \
it's a core language and it's possible to translate a good language to
these primitives, so try not to worry that it is impossible to write an
elimination for a w-type correctly first try.
btw, you can see in `elimNat` that the part after `with` is a partially applied
function. this seems to be the most common pattern for dependent eliminators,
which is why it's `rec n with s` instead of something like
`case n of (tag <| f, IH) => s[tag,f,IH]`.
getting rid of those `inf`s (and those in `elimNat`'s type) will need dependent
quantities arrrg
# type rules
:::defs
$$
\newcommand\Q{\mathrel|}
\newcommand\Z{\mathbf0}
\newcommand\Chk{\mathrel\Leftarrow}
\newcommand\Syn{\mathrel\Rightarrow}
\newcommand\Ty[3]{\frac{\begin{matrix}#2\end{matrix}}{#3}\;\mathbfsf{#1}}
\newcommand\AA{\textcolor{Purple}}
\newcommand\BB{\textcolor{OliveGreen}}
\newcommand\CC{\textcolor{RoyalBlue}}
\newcommand\DD{\textcolor{Bittersweet}}
\newcommand\EE{\textcolor{WildStrawberry}}
\newcommand\FF{\textcolor{PineGreen}}
\newcommand\GG{\textcolor{RedViolet}}
\newcommand\HH{\textcolor{RedOrange}}
$$
:::
:::rulebox
$$
\begin{gather}
\Psi \Q \Delta \Q \Gamma \vdash
\AA{s} \Chk \BB{A}
\dashv \AA{\delta_s}; \BB{\delta_A} \\[.1em]
\Psi \Q \Delta \Q \Gamma \vdash
\AA{e} \Syn \BB{A}
\dashv \AA{\delta_e}; \BB{\delta_A} \\
\end{gather}
$$
:::
ok. here we go. tybes. get ready for Density. to try and make things a little
easier to pick out, quantities will be colour coded with where they came from.
some of the colours are too similar. sorry.
$$
\begin{align*}
\Gamma &\EQ \cdot \Or \Gamma, x : A
& \text{type context} \\
\delta &\EQ \cdot \Or \delta, \pi x
& \text{quantity vector} \\
\Delta &\EQ \cdot \Or \Delta, \delta
& \text{quantity context} \\
\Psi &\EQ \cdot \Or \Psi, \iota \Or \Psi, q=r
& \text{cube}
\end{align*}
$$
a context $\Gamma$ is a list of types, as always.
a quantity context $\Delta$ is a triangle of how many times each type in
$\Gamma$ uses all the previous ones. $\delta$ is a single vector of quantities,
used for counting the quantities of everything in the subject and the subject's
type. $0\Gamma$ means a quantity vector with the variables of $\Gamma$, with
everything set to zero.
a :ice_cube: cube :ice_cube: collects the dimension variables in scope, and
constraints between them.
the grtt paper (which doesn't have cubes) has this example (but written slightly
differently):
$$
\left(\begin{smallmatrix}
\\
1 A \\
1 A & 0 x \\
\end{smallmatrix}\right) \Q
(A: \Type0, x: A, y: A) \vdash
\AA{x} \Syn \BB{A}
\dashv \AA{(0A,1x,0y)}; \BB{(1A,0x,0y)}
$$
in $\Delta$ (the big thing at the beginning):
- $A$ is the first element, so there is nothing it could mention, and it has
just an empty list $()$.
- $x: A$ contains $A$ once, which is the only option, so it has $(1A)$.
- $y: A$ also mentions $A$, but not $x$, so it's $(1A,0x)$.
after the type of the subject are two more quantity vectors. the first is how
the context elements are used in the subject itself, and the second how they're
used in its type.
by the way the reason i write the judgements this way with those two vectors at
the end is because they are outputs, so now everything before $\vdash$ is an
input, and everything after $\dashv$ is an output. whether the type is an input
or output varies: since the syntax is bidirectional, $s \Chk A$ means that
the term $s$ can only be checked against a known $A$ (so it's an input), and
$e \Syn A$ means that for an elimination $e$ the type $A$ can be inferred (so
it's an output).
## universes
$$
\Ty{type}{
\AA{\ell} < \BB{\ell'}
}{
\Psi \Q \Delta \Q \Gamma \vdash
\AA{\Type\ell} \Chk \BB{\Type{\ell'}}
\dashv 0\Gamma; 0\Gamma
}
$$
universes are cumulative. since we have a known universe to check against, why
not.
## functions
$$
\Ty{fun}{
\Psi \Q \Delta \Q \Gamma \vdash
\AA{A} \Chk \Type\ell
\dashv \AA{\delta_A}; 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\BB{B} \Chk \Type\ell
\dashv (\BB{\delta_B}, \EE\rho x); (0\Gamma, 0x) \\
}{
\Psi \Q \Delta \Q \Gamma \vdash
(x \Qty \DD\pi,\EE\rho : \AA{A}) \to \BB{B} \Chk \Type\ell
\dashv (\AA{\delta_A} + \BB{\delta_B}); 0\Gamma
}
$$
in formation rules like this, the type-level quantities being all zero doesn't
actually have to be checked, since everything is being checked against
$\Type\ell$ which never uses variables. if universe polymorphism starts existing
that will have to be tweaked in some way. maybe rules like __lam__ will have
$\AA{\delta_A}; \FF{\delta_\ell}$ in the output of the first premise, and
$\CC{\delta_t}; (\AA{\delta_A} + \BB{\delta_B} + \FF{\delta_\ell})$ in the
conclusion. something like that.
$$
\Ty{lam}{
\Psi \Q \Delta \Q \Gamma \vdash
\AA{A} \Chk \Type\ell
\dashv \AA{\delta_A}; 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\CC{t} \Chk \BB{B}
\dashv (\CC{\delta_t}; \DD\pi x); (\BB{\delta_B}; \EE\rho x) \\
}{
\Psi \Q \Delta \Q \Gamma \vdash
\lambda x. \CC{t} \Chk (x \Qty \DD\pi,\EE\rho : \AA{A}) \to \BB{B}
\dashv \CC{\delta_t}; (\AA{\delta_A} + \BB{\delta_B})
}
$$
$$
\Ty{app}{
\Psi \Q \Delta \Q \Gamma \vdash
\FF{f} \Syn (x \Qty \DD\pi,\EE\rho : \AA{A}) \to \BB{B}
\dashv \FF{\delta_f}; (\AA{\delta_A} + \BB{\delta_B}) \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\BB{B} \Chk \Type\ell
\dashv (\BB{\delta_B}, \EE\rho x); (0\Gamma, 0x) \\
\Psi \Q \Delta \Q \Gamma \vdash
\CC{s} \Chk \AA{A}
\dashv \CC{\delta_s}; \AA{\delta_A} \\
}{
\Psi \Q \Delta \Q \Gamma \vdash
\FF{f} \: \CC{s} \Syn \BB{B}[\CC{s}/x]
\dashv (\FF{\delta_f} + \DD\pi\CC{\delta_s});
(\BB{\delta_B} + \EE\rho\CC{\delta_s})
}
$$
the head of an application needs to inferrable, but a lambda isn't. so a
β redex is actually going to be something like
$\big((\lambda x. t) : (x \Qty \pi,\rho : A) \to B\big) \: t$
with an annotation on the head. probably from an inlined definition with a type
signature.
## pairs
$$
\Ty{pair}{
\Psi \Q \Delta \Q \Gamma \vdash
\AA{A} \Chk \Type\ell
\dashv \AA{\delta_A}; 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\BB{B} \Chk \Type\ell
\dashv (\BB{\delta_B}, \EE\rho x); 0\Gamma \\
}{
\Psi \Q \Delta \Q \Gamma \vdash
(x \Qty \EE\rho : \AA{A}) \times \BB{B} \Chk \Type\ell
\dashv (\AA{\delta_A} + \BB{\delta_B}); 0\Gamma
}
$$
$$
\Ty{comma}{
\Psi \Q \Delta \Q \Gamma \vdash
\CC{s} \Chk \AA{A}
\dashv \CC{\delta_s}; \AA{\delta_A} \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\BB{B} \Chk \Type\ell
\dashv (\BB{\delta_B}, \EE\rho x); 0\Gamma \\
\Psi \Q \Delta \Q \Gamma \vdash
\DD{t} \Chk \BB{B}[\CC{s}/x]
\dashv \DD{\delta_t}; (\BB{\delta_B} + \EE\rho\CC{\delta_s}) \\
}{
\Psi \Q \Delta \Q \Gamma \vdash
\Tup{\CC{s}, \DD{t}} \Chk (x \Qty \EE\rho : \AA{A}) \times \BB{B}
\dashv (\CC{\delta_s} + \DD{\delta_t}); (\AA{\delta_A} + \BB{\delta_B})
}
$$
$$
\Ty{casepair}{
\Psi \Q \Delta \Q \Gamma \vdash
\FF{e} \Syn (x \Qty \EE\rho : \AA{A}) \times \BB{B}
\dashv \FF{\delta_e}; (\AA{\delta_A} + \BB{\delta_B}) \\
\Psi \Q \Delta \Q \Gamma \vdash
\AA{A} \Chk \Type\ell
\dashv \AA{\delta_A}; 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A}) \Q (\Gamma, x : \AA{A}) \vdash
\BB{B} \Chk \Type\ell
\dashv (\BB{\delta_B}, \EE\rho x); 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A} + \BB{\delta_B})
\Q (\Gamma, z: (x \Qty \EE\rho : \AA{A}) \times \BB{B}) \vdash
\GG{C} \Chk \Type\ell
\dashv (\GG{\delta_C}, \HH\sigma z); 0\Gamma \\
\Psi \Q (\Delta, \AA{\delta_A}, (\BB{\delta_B}, \EE\rho))
\Q (\Gamma, x : \AA{A}, y : \BB{B}) \vdash
\CC{s} \Chk \GG{C}[\Tup{x, y}/z]
\dashv (\CC{\delta_s}, \DD\pi x, \DD\pi y);
(\GG{\delta_C}, \HH\sigma x, \HH\sigma y)
}{
\Psi \Q \Delta \Q \Gamma \vdash
(\Case \FF{e} \Return z. \GG{C} \Of \Tup{x, y} \Arr \CC{s})
\Syn \GG{C}[\FF{e}/z]
\dashv (\CC{\delta_s} + \DD\pi\FF{\delta_e});
(\GG{\delta_C} + \HH\sigma\FF{\delta_e})
}
$$
## inductive data
:^)
## enumerations
$$
\Ty{enum}{}{
\Psi \Q \Delta \Q \Gamma \vdash
\{ \overline{\L{a}_i}^i \} \Chk \Type\ell
\dashv 0\Gamma; 0\Gamma
}
$$
$$
\Ty{symbol}{
\L{a} \in \overline{\L{a}_i}^i
}{
\Psi \Q \Delta \Q \Gamma \vdash
\L{a} \Chk \{ \overline{\L{a}_i}^i \}
\dashv 0\Gamma; 0\Gamma
}
$$
$$
\Ty{caseenum}{
\Psi \Q \Delta \Q \Gamma \vdash
\FF{e} \Syn \{\L{a}_i\}
\dashv \FF{\delta_e}; 0\Gamma \qquad
\overline{
\Psi \Q \Delta \Q \Gamma \vdash
\CC{s_i} \Chk \AA{A}[\L{a}_i/z]
\dashv \CC{\delta_s}; \AA{\delta_A}
}^i
}{
\Psi \Q \Delta \Q \Gamma \vdash
\Case \FF{e} \Return z. \AA{A} \Of \{ \overline{\L{a}_i \Arr \CC{s_i}}^i \}
\dashv (\FF{\delta_e} + \CC{\delta_s}); \AA{\delta_A}
}
$$
__TODO__ the rest

100
posts/chrismas.md Normal file
View file

@ -0,0 +1,100 @@
---
date: 2023-12-25
title: merr chrismas
tags: [lántas, conlangs]
conlang: laantas
...
# just tell me how to say it please
sure thing. here.
:::glosses
- ufit þulkusimsari
- [ˌufit ˈθuɫkɔsĩsɐʒi]
- ufi-t þulkusi-m-sa-ri
- cozy-GEN midwinter-DEF-AD-PRL
- (be) cozy during midwinter
:::
# details
now i am not a huge fan of putting christianity into my conlang, which is
hopefully understandable. but having a midwinter festival sounds cute. the days
are finally getting longer! you made it through the worst part! and so on. so
that's what this is. i think it probably takes place the day after the solstice,
but with several days of festivities, so that there is still a little overlap
with the _other_ winter holiday. it's still appropriate to say it today.
## seasons
| time | name | | pron. | translation |
|----------|---------------|--------------|--------------|-------------|
| nov--jan | `{#igisim}` | `{igisim}` | `[ˈiʝɛsĩ]` | the freeze |
| feb | `{#susurum}` | `{susurum}` | `[ˈsusʊrõ]` | the melt |
| mar--may | `{#šangubam}` | `{šangubam}` | `[ˈʃaŋɡɔvɑ̃]` | the bloom |
| jun--aug | `{#guwanḿ}` | `{guwanḿ}` | `[ˈɡɔwɑnm̩]` | the sun |
| sep--oct | `{#santum}` | `{santum}` | `[ˈsantõ]` | the rain |
- in between `{!igisim}` (winter) and `{!šangubam}` (spring), the month of
february is considered a transition between the two, `{!susurum}`.
- as a result, `{!santum}` (autumn) is only two months long.
- `{!šangubam}` comes from `{!šani}` (flower) and `{!guba}` (grow, thrive).
## putting it together
the word "midwinter", without any inflections, is `{!þulkusim}`, which comes
from `{!þulku}` "be deep" and `{!igisim}`. unusually for lántas, `{!þulku}` is a
verb, rather than a noun. why? who knows.
::: {.aside .floating}
on that page, where you see a `{ƶ}`, replace it with `{þ}`. i haven't got round
to updating that yet. it also has the ugly text until i redraw `{!č\ ǧ\}`, since
at least if it's all ugly it's consistent. sorry about that.
:::
the suffix `{!sari}` is actually a pair of two suffixes, which together mean
through, or during. the details of the whole situation are [here][loc], but it
is a cool two-dimensional system based on a thing that can be found in some
languages of the caucasus. the `{!m}` on the end (of all these words so far,
actually) is "the". so the full form `{!þulkusimsari}` means "during midwinter".
now, for `{!ufit}`. there is a small, but technically non-zero, chance that you
remember the word `{!uf{a}t}` from [here][hallow], with the meaning of "warm".
this is actually the same word, but a bit cutesy. so, cozy.
the implied verb in this sentence is `{!iksaha}`, like before. this is an
auxiliary verb for requests. for example, if `{!šikkúha}` means "you are going",
then `{!šikkúm iksaha}` means "please go away". the `{ha}` here means "you"
(singular). here it's dropped because the phrase is long enough already to be
easily understood.
so in the end, you get `{!ufit þulkusimsari}`, meaning "[stay] cozy during the
midwinter".
:::twocol-grid
![](images/crismas1.png){width=100%}
::: {.glosses .left}
- þugusim ai
- [ˈθuɣɔsĩm‿ai]
- þugusi-m ai
- miwiner-DEF be
- it crismas
:::
![](images/crismas2.png){width=100%}
::: {.glosses .left}
- ufi þugusinhari
- [ˌufi ˈθuɣɔsĩŋxɑʒi]
- ufi-(t) þugusi-m-hari
- cozy-(GEN) miwiner-DEF-DURIN
- merr crismas
:::
:::
[loc]: https://lang.niss.website/laantas/nouns.html#locational-cases
[hallow]: https://cohost.org/niss/post/3366713-ufat-iksaha

182
quox.bib Normal file
View file

@ -0,0 +1,182 @@
% quantitative stuff
@inproceedings{grtt,
author = {Moon, Benjamin and Eades, III, Harley and Orchard, Dominic},
editor = {Yoshida, Nobuko},
title = {Graded Modal Dependent Type Theory},
booktitle = {Programming Languages and Systems:
European Symposium on Programming ({ESOP})},
series = {Lecture Notes in Computer Science},
volume = {12648},
pages = {462--490},
publisher = {Springer},
year = {2021},
url = {https://doi.org/10.1007/978-3-030-72019-3\_17},
doi = {10.1007/978-3-030-72019-3\_17}
}
@inproceedings{nuttin,
author = {Conor McBride},
editor = {Sam Lindley and Conor McBride and
Philip W. Trinder and Donald Sannella},
title = {I Got Plenty o' Nuttin'},
booktitle = {A List of Successes That Can Change the World---Essays Dedicated
to {P}hilip {W}adler on the Occasion of His 60th Birthday},
pages = {207--233},
publisher = {Springer},
year = {2016},
% url = {https://doi.org/10.1007/978-3-319-30936-1\_12},
url = {https://personal.cis.strath.ac.uk/conor.mcbride/PlentyO-CR.pdf},
}
@inproceedings{qtt,
author = {Robert Atkey},
editor = {Anuj Dawar and
Erich Grädel},
title = {Syntax and Semantics of Quantitative Type Theory},
booktitle = {Logic in Computer Science ({LICS})},
pages = {56--65},
publisher = {{ACM}},
year = {2018},
% url = {https://doi.org/10.1145/3209108.3209189},
url = {https://bentnib.org/quantitative-type-theory.pdf}
}
% observational stuff
@inproceedings{ott-now,
author = {Thorsten Altenkirch and Conor McBride and Wouter Swierstra},
editor = {Aaron Stump and Hongwei Xi},
title = {Observational equality, now!},
booktitle = {Programming Languages meets Program Verification ({PLPV})},
publisher = {{ACM}},
year = {2007},
url = {https://www.cs.nott.ac.uk/~psztxa/publ/obseqnow.pdf},
}
@inproceedings{ott-good,
author = {Loïc Pujet and Nicolas Tabareau},
title = {Observational equality: now for good},
booktitle = {Principles of Programming Languages ({POPL})},
pages = {1--27},
year = {2022},
url = {https://doi.org/10.1145/3498693},
doi = {10.1145/3498693},
}
@inproceedings{xtt,
author = {Jonathan Sterling and Carlo Angiuli and Daniel Gratzer},
editor = {Herman Geuvers},
title = {Cubical Syntax for Reflection-Free Extensional Equality},
booktitle = {Formal Structures for Computation and Deduction ({FSCD})},
series = {LIPIcs},
volume = {131},
pages = {31:1--31:25},
publisher = {Schloss Dagstuhl - Leibniz-Zentrum für Informatik},
year = {2019},
% url = {https://doi.org/10.4230/LIPIcs.FSCD.2019.31},
url = {https://arxiv.org/pdf/1904.08562.pdf},
doi = {10.4230/LIPIcs.FSCD.2019.31}
}
% Misc type stuff
@misc{crude,
author = {McBride, Conor},
title = {Crude but effective stratification (slides)},
url = {https://personal.cis.strath.ac.uk/conor.mcbride/Crude.pdf},
note = {Slides}
}
@misc{crude-blog,
author = {McBride, Conor},
title = {Crude but Effective Stratification},
url = {https://mazzo.li/epilogue/index.html%3Fp=857&cpage=1.html},
year = {2011},
}
@inproceedings{mugen,
author = {Hou (Favonia), Kuen-Bang and Angiuli, Carlo and Mullanix, Reed},
title = {An Order-Theoretic Analysis of Universe Polymorphism},
month = {jan},
year = {2023},
url = {https://doi.org/10.1145/3571250},
doi = {10.1145/3571250},
booktitle = {Principles of Programming Languages ({POPL})},
}
@article{bidi,
author = {Jana Dunfield and Neel Krishnaswami},
title = {Bidirectional Typing},
journal = {{ACM} Computing Surveys},
volume = {54},
number = {5},
year = {2022},
url = {https://doi.org/10.1145/3450952},
doi = {10.1145/3450952},
}
% Misc implementation
@article{expl-sub,
author = {Martín Abadi and Luca Cardelli and
Pierre{-}Louis Curien and Jean{-}Jacques Lévy},
title = {Explicit Substitutions},
journal = {Journal of Functional Programming},
volume = {1},
number = {4},
pages = {375--416},
year = {1991},
url = {http://lucacardelli.name/Papers/ExplicitSub.pdf}
}
% historical
@inproceedings{indices,
author = {Edwin C. Brady and Conor McBride and James McKinna},
editor = {Stefano Berardi and Mario Coppo and Ferruccio Damiani},
title = {Inductive Families Need Not Store Their Indices},
booktitle = {Types for Proofs and Programs ({TYPES})},
series = {Lecture Notes in Computer Science},
volume = {3085},
pages = {115--129},
publisher = {Springer},
year = {2003},
url = {https://doi.org/10.1007/978-3-540-24849-1\_8},
doi = {10.1007/978-3-540-24849-1\_8},
note = {\textit{i couldn't find a non-paywalled version, sorry!
but it's mostly for historical interest anyway}}
}
% blog post specific
@misc{nlab-wtype,
author = {{nLab authors}},
title = {{W}-type},
howpublished = {\url{https://ncatlab.org/nlab/show/W-type}},
note = {\href{https://ncatlab.org/nlab/revision/W-type/47}{revision 47}},
month = nov,
year = 2023
}
@book{martinlof84,
author = {Per Martin-Löf},
title = {Intuitionistic type theory},
series = {Studies in proof theory},
volume = {1},
publisher = {Bibliopolis},
year = {1984},
isbn = {978-88-7088-228-5},
url = {https://archive-pml.github.io/martin-lof/pdfs/Bibliopolis-Book-retypeset-1984.pdf}
}
% bullshit
@misc{hotminute,
author = {{Wiktionary}},
title = {Hot minute},
year = {2023},
url = {https://en.wiktionary.org/wiki/hot_minute},
}

View file

@ -2,63 +2,45 @@
--section-prefix: ''; --section-prefix: '';
} }
h1::before, h2::before, h3::before, h4::before, h5::before, h6::before { main :is(h1, h2, h3, h4, h5, h6):not(.unnumbered)::before {
padding-right: 1ex; padding-right: 1ex;
} }
main h1 { main h1:not(.unnumbered) { counter-increment: h1; }
counter-increment: h1; main h1 { counter-reset: h2 h3 h4 h5 h6; }
counter-reset: h2 h3 h4 h5 h6; main h1:not(.unnumbered)::before {
}
main h1::before {
content: var(--section-prefix) counter(h1); content: var(--section-prefix) counter(h1);
} }
main h2 { main h2:not(.unnumbered) { counter-increment: h2; }
counter-increment: h2; main h2:not(.unnumbered)::before {
counter-reset: h3 h4 h5 h6;
}
main h2::before {
content: var(--section-prefix) counter(h1) '.' counter(h2); content: var(--section-prefix) counter(h1) '.' counter(h2);
} }
main h2 { counter-reset: h3 h4 h5 h6; }
main h3 { main h3:not(.unnumbered) { counter-increment: h3; }
counter-increment: h3; main h3 { counter-reset: h4 h5 h6; }
counter-reset: h4 h5 h6; main h3:not(.unnumbered)::before {
}
main h3::before {
content: var(--section-prefix) counter(h1) '.' counter(h2) '.' counter(h3); content: var(--section-prefix) counter(h1) '.' counter(h2) '.' counter(h3);
} }
main h4 { main h4:not(.unnumbered) { counter-increment: h4; }
counter-increment: h4; main h4 { counter-reset: h5 h6; }
counter-reset: h5 h6; main h4:not(.unnumbered)::before {
}
main h4::before {
content: var(--section-prefix) content: var(--section-prefix)
counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4); counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4);
} }
main h5 { main h5:not(.unnumbered) { counter-increment: h5; }
counter-increment: h5; main h5 { counter-reset: h6; }
counter-reset: h6; main h5:not(.unnumbered)::before {
}
main h5::before {
content: var(--section-prefix) content: var(--section-prefix)
counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4) '.' counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4) '.'
counter(h5); counter(h5);
} }
main h6 { main h6:not(.unnumbered) { counter-increment: h6; }
counter-increment: h6; main h6:not(.unnumbered)::before {
}
main h6::before {
content: var(--section-prefix) content: var(--section-prefix)
counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4) '.' counter(h1) '.' counter(h2) '.' counter(h3) '.' counter(h4) '.'
counter(h5) '.' counter(h6); counter(h5) '.' counter(h6);

BIN
style/niss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -1,3 +1,4 @@
@import url(fonts/schola/schola.css);
@import url(fonts/muller/muller.css); @import url(fonts/muller/muller.css);
@import url(fonts/junius/junius.css); @import url(fonts/junius/junius.css);
@import url(fonts/pragmatapro/pragmatapro.css); @import url(fonts/pragmatapro/pragmatapro.css);
@ -14,7 +15,7 @@
:root { :root {
background: var(--root-col); background: var(--root-col);
font-family: Muller; font-family: schola;
font-size: 16pt; font-size: 16pt;
height: 100vh; height: 100vh;
@ -46,36 +47,38 @@ header h1 {
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin: 1em 0 0.25em; margin: 1em 0 0.25em;
font-family: Muller;
clear: both;
} }
h1 { h1 {
font-size: 200%; font-size: 150%;
font-weight: 200;
}
h2 {
font-size: 180%;
font-weight: 200;
}
h3 {
font-size: 160%;
font-weight: 300; font-weight: 300;
} }
h4 { h2 {
font-size: 140%; font-size: 140%;
font-weight: 300; font-weight: 300;
} }
h5 { h3 {
font-size: 130%;
font-weight: 300;
}
h4 {
font-size: 120%; font-size: 120%;
font-weight: 300;
}
h5 {
font-size: 110%;
font-weight: 400; font-weight: 400;
} }
h6 { h6 {
font-size: 100%; font-size: 100%;
font-weight: 400; font-weight: 600;
} }
header h1 { header h1 {
@ -142,6 +145,11 @@ b, strong {
font-weight: 600; font-weight: 600;
} }
dfn {
font-style: normal;
font-weight: 500;
}
ul li { ul li {
list-style: '— '; list-style: '— ';
} }
@ -172,6 +180,7 @@ code {
} }
pre { pre {
clear: both;
width: min-content; width: min-content;
margin: 0.5em auto; margin: 0.5em auto;
padding: 0.5em 0.8em; padding: 0.5em 0.8em;
@ -200,9 +209,9 @@ pre {
font-weight: 700; font-weight: 700;
} }
.abbr { .gloss .abbr {
font-size: 70%; font-size: 70%;
font-weight: 500; font-weight: bold;
} }
.scr { .scr {
@ -308,6 +317,15 @@ figure li {
break-inside: avoid; break-inside: avoid;
} }
figcaption {
font-size: 80%;
font-style: italic;
margin: auto;
}
:not(.floating) > figcaption {
width: 75%;
}
dt { font-weight: 500; float: left; clear: left; } dt { font-weight: 500; float: left; clear: left; }
dd { margin-left: 4em; } dd { margin-left: 4em; }
@ -336,7 +354,19 @@ u u {
margin-top: 0; margin-top: 0;
} }
.twocol-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1em;
margin: 1em 0;
}
.twocol-grid .gloss {
margin-left: 0;
}
footer { footer {
clear: both;
margin: 1.5em auto 1em; margin: 1.5em auto 1em;
padding-top: 0.5em; padding-top: 0.5em;
@ -385,24 +415,133 @@ blockquote {
} }
aside { .note, aside {
font-size: 90%; font-size: 90%;
margin: 0.5em 3em;
border-left: 2px solid var(--root-col);
padding-left: 1em;
} }
.note {
font-style: italic;
}
:is(h1, h2) .note {
font-size: 75%;
}
aside {
margin: 0.5em 3em;
padding-left: 1em;
}
aside:not(.no-line) {
border-left: 2px solid var(--root-col);
}
aside > details summary {
font-weight: 600;
}
aside :is(h1, h2, h3, h4, h5, h6) {
margin-top: 0.25em;
font-weight: 600;
}
aside h1 { font-size: 115%; }
aside :is(h2, h3, h4, h5, h6) { font-size: 100%; }
:is(aside, figure).floating {
max-width: 33%;
}
aside.floating {
padding: 0.25em 0.75em;
margin: 0.15em 1em 0;
}
figure.floating {
margin: 0 0.5em;
}
aside.floating :first-child { margin-top: 0; }
aside.floating :last-child { margin-bottom: 0; }
.kw { color: hsl(300deg, 60%, 30%); } .kw { color: hsl(300deg, 60%, 30%); }
.pp { color: hsl(343deg, 100%, 40%); /* font-weight: 500; */ } .pp { color: hsl(343deg, 100%, 40%); /* font-weight: 500; */ }
.dt { color: hsl(173deg, 100%, 24%); /* font-weight: 500; */ } .dt { color: hsl(173deg, 100%, 24%); /* font-weight: 500; */ }
.fu { color: hsl(34deg, 100%, 30%); /* font-weight: 500; */ } .fu, .at { color: hsl(34deg, 100%, 30%); /* font-weight: 500; */ }
.va { color: hsl(203deg, 100%, 30%); /* font-weight: 500; */ } .va { color: hsl(203deg, 100%, 30%); /* font-weight: 500; */ }
.cf { color: hsl(276deg, 75%, 35%); /* font-weight: 500; */ } .cf { color: hsl(276deg, 75%, 35%); /* font-weight: 500; */ }
.op { color: hsl(220deg, 40%, 33%); } .op { color: hsl(220deg, 40%, 33%); }
.co { color: hsl(221deg, 10%, 39%); font-style: italic; } .co { color: hsl(221deg, 10%, 39%); /* font-style: italic; */ }
.bu { color: hsl(120deg, 85%, 25%); } .bu { color: hsl(120deg, 85%, 25%); }
:is(.st, .fl, .dv, .sc) { color: hsl(143deg, 100%, 20%); } .st, .fl, .dv, .bn, .sc, .ss { color: hsl(143deg, 100%, 20%); }
.wa { color: hsl(350deg, 80%, 25%); text-decoration: wavy 1.5px underline; } .wa { color: hsl(350deg, 80%, 25%); text-decoration: wavy 1.5px underline; }
.al { color: hsl(350deg, 80%, 25%); } .al { color: hsl(350deg, 80%, 25%); }
.cn { color: hsl(343deg, 100%, 30%); } .cn { color: hsl(343deg, 100%, 30%); }
.floating {
float: right;
margin: 0.5em 1em 0.5em 2em;
}
.floating.left {
float: left;
margin: 0.5em 2em 0.5em 1em;
}
.shaped {
/* maybe one day... */
/* shape-outside: attr(src url); */
shape-margin: 1em;
}
.shadow { filter: drop-shadow(5px 5px 8px #0006); }
.pixel {
image-rendering: crisp-edges;
image-rendering: pixelated;
}
.citation {
font-size: 90%;
}
#refs {
margin-top: 0.75em;
}
.csl-entry {
margin-left: 2em;
text-indent: -2em;
}
/*
.csl-entry {
display: grid;
grid-template-columns: 4ch auto;
grid-gap: 1ex;
}
.csl-left-margin {
justify-self: end;
}
*/
.texdefs {
display: none;
}
.rulebox {
float: right;
border: 1px solid var(--root-col);
background: #ffffff66;
padding: .4em 1.2em;
}
/* the last thing in the :is is for priority fuckery */
.rulebox :is(p, .math, mjx-container, #asd) {
margin: 0;
padding: 0;
}
.clear { clear: both; }
mark {
mix-blend-mode: multiply;
background: #fbc;
padding: 0 0.35ch;
}

167
syntax/quox.xml Normal file
View file

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd" [
<!ENTITY tok_start "(?&lt;=^|\s|[(\[{}\]),:.])">
<!ENTITY tok_end "(?=$|\s|[(\[{}\]),:.])">
<!ENTITY hexit "[0-9a-fA-F]">
]>
<language name="quox" section="Sources" extensions="*.quox"
version="1" kateversion="5.53">
<highlighting>
<list name="load"> <item>load</item> </list>
<list name="types">
<item>String</item>
<item>IOState</item>
<item></item> <item>Nat</item>
<item>Eq</item>
<item>Type</item>
</list>
<list name="exprs">
<item>fst</item> <item>snd</item>
<item>coe</item> <item>comp</item>
<item>λ</item> <item>fun</item>
<item>δ</item> <item>dfun</item>
<item>return</item> <item>of</item>
<item>return</item> <item>of</item>
<item>zero</item> <item>succ</item>
</list>
<list name="attrs">
<item>fail</item>
<item>main</item>
<item>compile-scheme</item>
</list>
<contexts>
<context attribute="default" lineEndContext="#stay" name="Default">
<keyword attribute="load" context="#stay" String="load" />
<RegExpr attribute="defs" context="qty_suffix"
String="\b(def|postulate)(?=([01#]|ω)?\b)" />
<keyword attribute="types" context="#stay" String="types" />
<DetectChar attribute="types" context="#stay" char="★" />
<DetectChar attribute="types" context="#stay" char="×" />
<Detect2Chars attribute="types" context="#stay" char="*" char1="*" />
<DetectChar attribute="types" context="#stay" char="→" />
<Detect2Chars attribute="types" context="#stay" char="-" char1=">" />
<DetectChar attribute="types" context="#stay" char="≡" />
<Detect2Chars attribute="types" context="#stay" char="=" char1="=" />
<keyword attribute="exprs" context="#stay" String="exprs" />
<DetectChar attribute="exprs" context="#stay" char="∷" />
<Detect2Chars attribute="exprs" context="#stay" char=":" char1=":" />
<DetectChar attribute="exprs" context="#stay" char="," />
<DetectChar attribute="exprs" context="#stay" char="⇒" />
<Detect2Chars attribute="exprs" context="#stay" char="=" char1=">" />
<RegExpr attribute="exprs" context="qty_suffix"
String="\bcase(?=([01#]|ω)?\b)" />
<RegExpr attribute="hex_nat" context="#stay"
String="\b0[xX]&hexit;((&hexit;|_)*&hexit;)?\b(?!\.)" />
<RegExpr attribute="dec_nat" context="#stay"
String="\b\d((\d|_)*\d)?\b(?!\.)" />
<DetectChar attribute="string" context="String" char="&quot;" />
<Detect2Chars attribute="tag" context="Tag"
char="'" char1="&quot;" />
<RegExpr attribute="tag" context="#stay"
String="(?&lt;!\w|-|')'(\w|-|')+" />
<RegExpr attribute="qty" context="#stay"
String="\b([01#]|ω)\.(?!\d)" />
<DetectChar attribute="punc" context="#stay" char="=" />
<DetectChar attribute="punc" context="#stay" char="@" />
<Detect2Chars attribute="attr" context="attr" char="#" char1="[" />
<Detect2Chars attribute="comment" context="comment_s"
char="-" char1="-" />
<Detect2Chars attribute="comment" context="comment_m"
char="{" char1="-" />
</context>
<context attribute="qty" lineEndContext="#pop" name="qty_suffix">
<RegExpr attribute="qty" context="#stay" String="([01#]|ω)?\b" />
<RegExpr attribute="normal" context="#pop" String="\s|$" />
</context>
<context attribute="string" lineEndContext="#stay" name="String">
<Detect2Chars attribute="string_esc" context="#stay"
char="\" char1="&quot;" />
<Detect2Chars attribute="string_esc" context="#stay"
char="\" char1="\" />
<Detect2Chars attribute="string_esc" context="#stay"
char="\" char1="n" />
<Detect2Chars attribute="string_esc" context="#stay"
char="\" char1="t" />
<RegExpr attribute="string_esc" context="#stay"
String="\\x&hexit;+;" />
<DetectChar attribute="string" context="#pop" char="&quot;" />
</context>
<context attribute="tag" lineEndContext="#stay" name="Tag">
<Detect2Chars attribute="tag_esc" context="#stay"
char="\" char1="&quot;" />
<Detect2Chars attribute="tag_esc" context="#stay"
char="\" char1="\" />
<Detect2Chars attribute="tag_esc" context="#stay"
char="\" char1="n" />
<Detect2Chars attribute="tag_esc" context="#stay"
char="\" char1="t" />
<RegExpr attribute="tag_esc" context="#stay"
String="\\x&hexit;+;" />
<DetectChar attribute="tag" context="#pop" char="&quot;" />
</context>
<context attribute="attr" lineEndContext="#stay" name="attr">
<DetectChar attribute="string" context="String" char="&quot;" />
<DetectChar attribute="attr" context="attr" char="[" />
<DetectChar attribute="attr" context="#pop" char="]" />
<keyword attribute="attr_name" context="#stay" String="attrs" />
</context>
<context attribute="comment" lineEndContext="#pop" name="comment_s" />
<context attribute="comment" lineEndContext="#stay" name="comment_m">
<Detect2Chars attribute="comment" context="comment_m"
char="{" char1="-" />
<Detect2Chars attribute="comment" context="#pop"
char="-" char1="}" />
</context>
</contexts>
<itemDatas>
<itemData name="default" defStyleNum="dsNormal" />
<itemData name="load" defStyleNum="dsPreprocessor" />
<itemData name="defs" defStyleNum="dsFunction" />
<itemData name="types" defStyleNum="dsDataType" />
<itemData name="exprs" defStyleNum="dsControlFlow" />
<itemData name="dec_nat" defStyleNum="dsDecVal" />
<itemData name="hex_nat" defStyleNum="dsBaseN" />
<itemData name="string" defStyleNum="dsString" />
<itemData name="string_esc" defStyleNum="dsSpecialChar" />
<itemData name="tag" defStyleNum="dsSpecialString" />
<itemData name="tag_esc" defStyleNum="dsSpecialChar" />
<itemData name="qty" defStyleNum="dsBuiltIn" />
<itemData name="punc" defStyleNum="dsNormal" />
<itemData name="attr" defStyleNum="dsNormal" />
<itemData name="attr_name" defStyleNum="dsAttribute" />
<itemData name="comment" defStyleNum="dsComment" />
</itemDatas>
</highlighting>
<general>
<keywords casesensitive="true" weakDeliminator="-'" />
</general>
</language>

View file

@ -25,7 +25,7 @@ $head()$
$if(show-toc)$ $if(show-toc)$
<nav id=toc> <nav id=toc>
<h2>Contents</h2> <h2>contents</h2>
$table-of-contents$ $table-of-contents$
</nav> </nav>