diff --git a/.gitignore b/.gitignore index d2a6a5a..4f19501 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ dist-newstyle _build _tmp +.directory +*~ diff --git a/images/bub_flop.png b/images/bub_flop.png new file mode 100644 index 0000000..3af302d Binary files /dev/null and b/images/bub_flop.png differ diff --git a/images/crismas1.png b/images/crismas1.png deleted file mode 100644 index e7b98cd..0000000 Binary files a/images/crismas1.png and /dev/null differ diff --git a/images/crismas2.png b/images/crismas2.png deleted file mode 100644 index 7097ee9..0000000 Binary files a/images/crismas2.png and /dev/null differ diff --git a/images/panqt.nobg.png b/images/panqt.nobg.png deleted file mode 100644 index ecdadf6..0000000 Binary files a/images/panqt.nobg.png and /dev/null differ diff --git a/images/panqt.nobg2x.png b/images/panqt.nobg2x.png deleted file mode 100644 index 7598716..0000000 Binary files a/images/panqt.nobg2x.png and /dev/null differ diff --git a/images/panqt.png b/images/panqt.png deleted file mode 100644 index 43e5080..0000000 Binary files a/images/panqt.png and /dev/null differ diff --git a/images/panqt2x.png b/images/panqt2x.png deleted file mode 100644 index 8e405cb..0000000 Binary files a/images/panqt2x.png and /dev/null differ diff --git a/images/qt.svg b/images/qt.svg deleted file mode 100644 index a7caf28..0000000 --- a/images/qt.svg +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/images/quorientation.png b/images/quorientation.png deleted file mode 100644 index 8af38fb..0000000 Binary files a/images/quorientation.png and /dev/null differ diff --git a/images/quox-tod.png b/images/quox-tod.png deleted file mode 100644 index b9edb50..0000000 Binary files a/images/quox-tod.png and /dev/null differ diff --git a/images/quox.png b/images/quox.png deleted file mode 100644 index 96bf9f4..0000000 Binary files a/images/quox.png and /dev/null differ diff --git a/images/skip-some-floors.png b/images/skip-some-floors.png deleted file mode 100644 index f5601dd..0000000 Binary files a/images/skip-some-floors.png and /dev/null differ diff --git a/images/yummycricket.png b/images/yummycricket.png deleted file mode 100644 index 2953d7b..0000000 Binary files a/images/yummycricket.png and /dev/null differ diff --git a/posts-wip/2023-06-05-quox.md b/posts-wip/2023-06-05-quox.md deleted file mode 100644 index 2e5a53b..0000000 --- a/posts-wip/2023-06-05-quox.md +++ /dev/null @@ -1,315 +0,0 @@ ---- -title: intro to quox -date: 2023-06-05 -tags: [computer, quox (language)] -show-toc: true -bibliography: quox.bib -link-citations: true -... - -
- quox sprite from quest of ki -
(this is a quox)
-
- -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 dependent type 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 -
-but i can do that in rust/c++/haskell too - -yeah! well, partially. in rust you can have like - -```rust -fn replicate(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. -
-::: - -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 - - - -```quox -def backwards-plus : ω.ℕ → ω.ℕ → ℕ = - λ a b ⇒ plus b a -``` - -:::aside -
-what does all that mean - -- 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 - ``` -
-::: - -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 redex (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. whnf ([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 -
-`So` considered harmful, or whatever - -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. -
-::: - -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 quantity, 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; -erased), `1` (exactly once; linear), and `ω` (any number -of times; unrestricted, 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 borrowing 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} diff --git a/posts-wip/2023-10-25-quox.md b/posts-wip/2023-10-25-quox.md deleted file mode 100644 index e792b2e..0000000 --- a/posts-wip/2023-10-25-quox.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: quox. the language -date: 2023-10-25 -tags: [quox, computer, types] -bibliography: quox.bib -link-citations: true -show-toc: true -... - - - - -:::{.aside .floating} -### [hot minute][wkt] *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], i’ve been working on a little programming language. it’s 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} - -
- a dragon from an old arcade game -
this is also a quox.
-
- -0. it’s 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 don’t 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 - -
-
one of my fursonas is a quox with three heads
-
- sometimes i am also a quox. or three, depending on how you count. -
-
- -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} diff --git a/posts-wip/quox-type-system.md b/posts-wip/quox-type-system.md deleted file mode 100644 index 7ea3d6c..0000000 --- a/posts-wip/quox-type-system.md +++ /dev/null @@ -1,513 +0,0 @@ ---- -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 #⁠UIP⁠Crew - - - -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. :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 diff --git a/posts-wip/rainbow-quox.md b/posts-wip/rainbow-quox.md new file mode 100644 index 0000000..84186c4 --- /dev/null +++ b/posts-wip/rainbow-quox.md @@ -0,0 +1,274 @@ +--- +title: rainbow quox +date: 2024-11-17 +tags: [computer, website, fursona] +summary: q.t. colour scheme generator +... + +so how about that regular posting, huh. ha ha ha + +i haven't been up to much unusual. [drawing], mostly. i installed [nixos] on both my computers and it's going pretty well so far [(less than a week)]{.note}, but every computer toucher does that at some point, so, whatever. + +[drawing]: https://gallery.niss.website +[nixos]: https://nixos.org + +anyway, to the point. + +:::banner +[go here if you just want to play with the thing][thing] + +::: + +# the point {.unnumbered} + +the animal-inclined might know that [q.t.][qt] can change its colour any time it wants. if you click that link you can clearly see i have some tendencies, but it can in theory be anything. so something i have wanted for a while is a page where you can click a button and get a bespoke randomly-generated quox theme of your very own. + +so i did that. + +:::aside +you can also skip to [what i _actually_ ended up doing](#actual), if you don't care about the false starts. +::: + +[qt]: https://gallery.niss.website/by-any/#qt + +# doing that + +![this is the image i'm starting from.](rainbow-quox/front.avif){.floating .expandable .nobg .shaped} + +pretty much what i want to do, at least to begin with, is take the original colours of the image and move the hues around at random. + +if you look at [mdn], you might see this interesting [`hue-rotate()`][hr] thing that might do what i want. let's have a look. + +[mdn]: https://developer.mozilla.org/en-US/docs/Web/CSS +[hr]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/hue-rotate + +> **Note:** `hue-rotate()` is specified as a matrix operation on the RGB color. It does not actually convert the color to the HSL model, which is a non-linear operation. Therefore, it may not preserve the saturation or lightness of the original color, especially for saturated colors. + +well that doesn't sound very promising. but maybe it'll be fine, so let's try it. first, separate the pictures from [q.t.'s refsheet][ref] into bits. like this. + +[ref]: https://gallery.niss.website/main/niss/2024-06-27-qt + +![sock stripes, belly, main body, and masks/claws should change independently from each other. the other colours don't change.](rainbow-quox/pieces1.avif){.expandable .lightbg} + +now let's layer them back on top of each other with some css. + +```html + + + +
+ + + +
+``` + +![took a hot shower for too long](rainbow-quox/red.avif){.floating .left .nobg .expandable .shaped} + +ok, next, actually try to do the hue stuff. to check it works at all, i shoved everything to hue 0° (using krita's _hue HSL_ blend mode), and used `hue-rotate()` to change it back to the 'main' colour of each region---it won't look exact, but it'll be close. + +```css +#container img { filter: hue-rotate(var(--hue)); } + +#outer { --hue: 273deg; } #belly { --hue: 26deg; } +#eyes { --hue: 133deg; } #masks { --hue: 284deg; } +#stripes { --hue: 188deg; } #lines { --hue: 273deg; } +/* also add the id to each image */ +``` + +right? + +![oh](rainbow-quox/dark.avif){.expandable .nobg} + +well that's no good at all. i guess that warning was serious. + +# ok what about blend modes + +![shoutout to the four different types of "soft light"](rainbow-quox/blends.avif){.floating .expandable} + +all right, fine. what else. as a chronic over-user of `overlay`, i can certainly tell you that css has a few [blending modes][bm]. not as many as krita, which has approximately "too many", but enough for most purposes. one of them is `hue`. how about that. + +[bm]: https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode + +this takes a bit more messing, because i need to create a flood fill of one of the colours from that layer, and blend with that. so how about an SVG filter, i guess. or, six SVG filters---one for each filter, since you can't parametrise them. + +time to copy and paste the same five lines six times. yaaaaaaaaay + +![ugh](../images/bub_flop.png){.bigemoji .pixel} \ + +```svg + + + + + + + + + +``` + +```css +#outer { filter: url(#fouter); } +/* …etc… */ +``` + +and… + +![also no](rainbow-quox/dark2.avif){.expandable .nobg} + +i was expecting at least the same thing, but a different, also wrong, result is pretty cool. + +# drastic measures {#actual} + +ok, enough messing around, time to bite the bullet. separate every single colour into its own layer, and use those as _masks_ for colour fills. + +now the pieces look like _this_: + +![this image is probably incomprehensible now. it doesn't really matter---the main thing is that there are seventeen different layers.](rainbow-quox/pieces2.avif){.expandable .lightbg} + +the colours in the images no longer matters, only the alpha channel. [(except for the eyes.)]{.note} each one is just a mask over a background fill of the right colour. + +```css +@layer { + #container { position: relative; width: 90vw; aspect-ratio: 3439/2240; } + #container div { position: absolute; inset: 0; mask-size: contain; } +} + +@layer { + #static { background: url(front/static.png) 0 0 / contain; } + #eye-shine { + background: url(front/eyes.png) 0 0 / contain; + mix-blend-mode: luminosity; + } + /* the others all look like this: */ + #spines { + background: oklch(30.77% 0.1306 var(--hue)); --hue: 298.19; + mask-image: url(front/spines.png); + } + /* etc… */ +} +``` + +```html +
+ +
+
+
+ +
+
+``` + +since the hue is separated out into a variable, i can just do: + +```js +for (const elem of document.getElementsByClassName('part')) { + elem.style.setProperty('--hue', Math.random() * 360); +} +``` + +and instantly i have _something_ working. i used `oklch` because it was more likely than `hsl` or whatever to keep the colours the same kind of distance from each other, since that is what it's designed for. + +![some of these are kinda promising already??](rainbow-quox/quoxes1.avif){.expandable .hasborder} + + +# keeping the colours in sync + +so as of last year, most browsers got a thing called [relative colours]. if you have an existing colour `--hi`, you can rotate its hue by half a turn by saying something like + +[relative colours]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors + +```css +:root { + --hi: #ea9aa1; + --wow: oklch(from var(--hi) l c calc(h + 180)); +} +``` + +--- +header-includes: | + +... + +
+
\--hi
+
\--wow
+
+ +you're taking the value of `var(--hi)`, keeping the lightness and chroma channels the same, and adding 180° to the hue. + +:::aside +that's not quite true. safari, as always, does it slightly wrong. according to the spec, all channels in a relative colour must be dimensionless, but in safari, the hue is an ``. other browsers, following the spec correctly, _don't allow_ that. so you _actually_ have to write + +```css +:root { + --hi: #ea9aa1; + --wow: oklch(from var(--hi) l c calc(h + 180)); +} +@supports (color: oklch(from red l c 10deg)) { + :root { --wow: oklch(from var(--hi) l c calc(h + 180deg)); } +} +``` + +thanks apple! +::: + +so based on that, i can pick one initial colour and base all the others on it. like + +```css +:root { + /* these aren't attempting to be the same colours, just guessing something + that MIGHT look nice */ + --outer: #57267e; + --spines: oklch(from var(--outer) calc(l * .75) calc(c * 1.25) h); + --vitiligo1: oklch(from var(--outer) calc(1 - (1 - l)/4) calc(c / 2) h); + + /* static l/c values because the socks are always some pale colour */ + --stripes: oklch(from var(--outer) .9 12.5% calc(h + 120)); + --cuffs: oklch(from var(--stripes) .8 25% h); + /* etc */ +} + +.outer { background: var(--outer); mask-image: url(front/outer.png); } +/* etc */ +``` + +so after guessing a bunch of relative colours, i ended up with this: + +![yeah that looks ok for a first try.](rainbow-quox/relative.avif){.expandable .nobg} + + +## notes for niss. if this goes online i fucked up + +- palette types +- randomise distance between analogous colours +- light, dark, light-dark, dark-light (belly vs outer) +- reinstate chaos mode +- can you set the random seed in the browser + - no. anyway the algorithm might be different + - make yr own + - or . whatever +- if so: use that to make palette permalinks diff --git a/posts-wip/rainbow-quox/blends.avif b/posts-wip/rainbow-quox/blends.avif new file mode 100644 index 0000000..e6904bc Binary files /dev/null and b/posts-wip/rainbow-quox/blends.avif differ diff --git a/posts-wip/rainbow-quox/dark.avif b/posts-wip/rainbow-quox/dark.avif new file mode 100644 index 0000000..c75851f Binary files /dev/null and b/posts-wip/rainbow-quox/dark.avif differ diff --git a/posts-wip/rainbow-quox/dark2.avif b/posts-wip/rainbow-quox/dark2.avif new file mode 100644 index 0000000..58be28b Binary files /dev/null and b/posts-wip/rainbow-quox/dark2.avif differ diff --git a/posts-wip/rainbow-quox/front.avif b/posts-wip/rainbow-quox/front.avif new file mode 100644 index 0000000..65bc2ba Binary files /dev/null and b/posts-wip/rainbow-quox/front.avif differ diff --git a/posts-wip/rainbow-quox/pieces1.avif b/posts-wip/rainbow-quox/pieces1.avif new file mode 100644 index 0000000..dcad189 Binary files /dev/null and b/posts-wip/rainbow-quox/pieces1.avif differ diff --git a/posts-wip/rainbow-quox/pieces2.avif b/posts-wip/rainbow-quox/pieces2.avif new file mode 100644 index 0000000..4b3e60a Binary files /dev/null and b/posts-wip/rainbow-quox/pieces2.avif differ diff --git a/posts-wip/rainbow-quox/quoxes1.avif b/posts-wip/rainbow-quox/quoxes1.avif new file mode 100644 index 0000000..3060729 Binary files /dev/null and b/posts-wip/rainbow-quox/quoxes1.avif differ diff --git a/posts-wip/rainbow-quox/red.avif b/posts-wip/rainbow-quox/red.avif new file mode 100644 index 0000000..1a45b94 Binary files /dev/null and b/posts-wip/rainbow-quox/red.avif differ diff --git a/posts-wip/rainbow-quox/relative.avif b/posts-wip/rainbow-quox/relative.avif new file mode 100644 index 0000000..93a16df Binary files /dev/null and b/posts-wip/rainbow-quox/relative.avif differ diff --git a/posts/chrismas.md b/posts/chrismas.md index 08cfb13..d038f4d 100644 --- a/posts/chrismas.md +++ b/posts/chrismas.md @@ -1,7 +1,7 @@ --- date: 2023-12-25 title: merr chrismas -tags: [lántas, conlangs] +tags: [lántas, conlangs, fursona] conlang: laantas summary: | how to say "merr chrismas" in my conlang lántas. @@ -80,7 +80,11 @@ midwinter". ::: {.twocol-grid .light} -![](images/crismas1.png){width=100%} +
+ + + +
::: {.glosses .left} - þugusim ai @@ -90,7 +94,11 @@ midwinter". - it crismas ::: -![](images/crismas2.png){width=100%} +
+ + + +
::: {.glosses .left} - ufi þugusinhari diff --git a/posts/chrismas/1.webp b/posts/chrismas/1.webp new file mode 100644 index 0000000..463b3e6 Binary files /dev/null and b/posts/chrismas/1.webp differ diff --git a/posts/chrismas/2.webp b/posts/chrismas/2.webp new file mode 100644 index 0000000..fc57f89 Binary files /dev/null and b/posts/chrismas/2.webp differ diff --git a/posts/cube.md b/posts/cube.md index 4a54544..3a405a8 100644 --- a/posts/cube.md +++ b/posts/cube.md @@ -6,7 +6,7 @@ summary: > i redesigned my personal website. it was a bit of an ordeal. ... -![this is the most complex web page i have ever made by a huge margin](/images/yummycricket.png){.floating .right} +![this is the most complex web page i have ever made by a huge margin](/cube/cube.webp){.floating .right .expandable} so for the past little while i've been making a big update to my [personal website]. it's a cube now! i wanted to make sure it worked in several browsers: diff --git a/posts/cube/cube.webp b/posts/cube/cube.webp new file mode 100644 index 0000000..1f4cafe Binary files /dev/null and b/posts/cube/cube.webp differ diff --git a/posts/first-person-pronouns.md b/posts/first-person-pronouns.md new file mode 100644 index 0000000..2834419 --- /dev/null +++ b/posts/first-person-pronouns.md @@ -0,0 +1,129 @@ +--- +title: lántas pronoun update +date: 2024-11-25 +tags: [lántas, conlangs] +conlang: laantas +summary: first-person neopronouns. and… neoinflections? +... + +so my "main" conlang [`@lántas@`][l] is actually kind of old at this point. old enough that when i made the personal pronouns, i didn't know that plurality was a thing that existed, so until today, the first person pronouns were `{!ká}` in the singular, and `{!til}` in the [(grammatical)]{.note} plural. except that `{til}` is an [`@inclusive@`][clus] pronoun, meaning it can only be used when the listener is included. which, as you can see from the fact it has a wikipedia article, is a thing that real life languages do sometimes. + +[l]: https://lang.niss.website/laantas +[clus]: https://en.wikipedia.org/wiki/Clusivity + +however, when someone uses "we" to mean "me and my headmates", that is (usually??) an exclusive usage. which means you can't use `{til}`, or the first-person plural verb inflection, and instead have to say `{#kakas rú, rúl}` `{kakas rú(l)}`, or "me and them". which is… pretty awkward. + +it's time to get a new one. + +# pronouns + +:::{.figure .hugescr .floating .right} +`{#kál}` +::: + +it seems that it would be pretty unlikely, given people's general _attitudes_, that a personal pronoun dedicated to plurality would arise naturally. so this is the perfect opportunity to have a `@neopronoun@`. without grammatical gender existing in the first place, there's no particular pressure for a new third-person pronoun to crop up. `{!rú}` (or `{!rúl}`) fits everyone just fine. as far as i know, anyway. + +so, `{!kál}`. it is pretty transparently the singular pronoun with the regular plural ending, `{!ká–l}`. but that's fine. it fits in with `{!rú}`, `{!rúl}` 'he/she/they (sg)/etc, they (pl)', and _almost_ with `{!sur}`, `{!sual}` 'you (sg)/you (pl)' too. + +`{!kál}` inflects almost like a regular noun with `{!ka–}` stem, except for the COM, which matches `{!tiksł}` and `{!ruksł}`, and the locative cases, which keep the long vowel like `{!ká}` does. + +in the table `!SPL!` stands for `@system plural@` i guess. (and `!IPL!` for `@inclusive plural@`; the old thing.) + +--- +header-includes: | + +... + + + + + + + + + + + + +
+ 1SG + 1SPL + 1EPL +
NOM + `{!ká}` + `{!kál}` + `{!til}` +
GEN + `{!kat}` + `{!katł}` + `{!tial}` +
COM + `{!kakas}` + `{!kaksł}` + `{!tiksł}` +
CAR + `{!kassa}` + `{!kassal}` + `{!tissal}` +
INS + `{!kala}` + `{!kalal}` + `{!tilla}` +
ESS + `{!kugu}` + `{!kugul}` + `{!tigul}` +
TRA + `{!kasti}` + `{!kastil}` + `{!tistil}` +
EXE + `{!kaču}` + `{!kačul}` + `{!tičul}` +
LOC + `{!ká–}` + `{!ká–l}` + `{!tí–l}` +
+ + +see [§3–4 of the noun page][cases] for inadequate descriptions of these cases that one day i will maybe expand on. + +[cases]: https://lang.niss.website/laantas/nouns.html#corecases + +# verb inflections + +:::{.figure .hugescr .floating .right} +`{#–káš}`
`{#–kúš}` +::: + +the existing [person suffixes][ps] for verbs actually have no resemblance at all to the pronouns. the new one does though. after all, it's new! it's `{!–káš}` for the subject and `{!–kúš}` for the object. + +[ps]: http://lang.niss.website/laantas/verbs.html#person + + + + + +
+ 1SG + 1SPL + 1EPL +
SBJ + `{!–na}` + `{!–káš}` + `{!–náš}` +
OBJ + `{!–du}` + `{!–kúš}` + `{!–dúš}` +
diff --git a/posts/goodbye-cohost.md b/posts/goodbye-cohost.md new file mode 100644 index 0000000..955f34c --- /dev/null +++ b/posts/goodbye-cohost.md @@ -0,0 +1,62 @@ +--- +title: goodbye cohost +tags: [misc] +date: 2024-10-01 +summary: thanks for being a website. +header-includes: | + +... + +```{=html} + +
HIGH SCORE +6969420 6969420 + + CONGRATURATIONS !! + + NOW YOU SAVE EGGBUG + AND + THE ADVENTURE IS OVER + + THANK YOU + FROM +WEB SITE jkap + vogon +GRAPHIC DESIGN aidan +MODERATION kaara + AND + AMUSEMENT CREATER + +
+``` + +thanks for being a website. diff --git a/posts/goodbye-cohost/PressStart2P-Regular.ttf b/posts/goodbye-cohost/PressStart2P-Regular.ttf new file mode 100644 index 0000000..1098ed2 Binary files /dev/null and b/posts/goodbye-cohost/PressStart2P-Regular.ttf differ diff --git a/posts/goodbye-cohost/PressStart2P-Regular.woff2 b/posts/goodbye-cohost/PressStart2P-Regular.woff2 new file mode 100644 index 0000000..c6c87e4 Binary files /dev/null and b/posts/goodbye-cohost/PressStart2P-Regular.woff2 differ diff --git a/posts/goodbye-cohost/cohost.svg b/posts/goodbye-cohost/cohost.svg new file mode 100644 index 0000000..e43713e --- /dev/null +++ b/posts/goodbye-cohost/cohost.svg @@ -0,0 +1 @@ + diff --git a/posts/goodbye-cohost/hiscore.mp3 b/posts/goodbye-cohost/hiscore.mp3 new file mode 100644 index 0000000..041c78f Binary files /dev/null and b/posts/goodbye-cohost/hiscore.mp3 differ diff --git a/posts/qt-refsheet.md b/posts/qt-refsheet.md new file mode 100644 index 0000000..1155d39 --- /dev/null +++ b/posts/qt-refsheet.md @@ -0,0 +1,92 @@ +--- +title: q.t. refsheet transcriptions +date: 2024-11-26 +tags: [fursona, lántas, conlangs] +conlang: laantas +summary: quick post for the text on q.t.'s refsheet +... + +:::figure + +![q.t.'s new refsheet. now bilingual](qt-refsheet/ref.webp) + +::: + +fitting lántas into a strictly eight-pixel high font was… difficult. and involved a lot of special-casing. it would be a huge hassle to get a computer to do it automatically. + +anyway let's get to it + +:::{.glosses .left} +- kuaksat pasaga +- [ˈkɔə̯ksət ˌpasəɣɐ] +- kuaksa-t pas-aga +- quox-GEN two-body +- quox taur + +--- + +- #6# mitral. #19# fútkasł #8# inčil +- [ˌdʒutːə ˈmitɾɐl ‖ ˌtaksɪːstʊ ˈfuːtkɑsɫ | ˌn̩daː ˈʔintʃiɬʲ] +- ǧutta mitra-l. taks(a)-ístu fút-kas-ł ńdá inči-l +- six metre-PL. ten-nine foot-COM-PL eight inch-PL +- 6m. 19′ 8″ + +--- + +- #376666# kígíl +- [ˌkɑɫːeˌbuʃɻ̩ ˌlivɪnɐˌtaksə ˌdʒutːəˌxɑːruəɬʲ dʒutːəbuʃɻ̩ ˌdʒutːɐtʃutːə ˈkɛːʝɛɬʲ] +- kalli-bušŕ libina-taksa-ǧutta-hárual ǧutta-bušŕ ǧuttaččutta kígí-l +- 3 76 6 66 kg-PL +- 376,666 kg + +--- + +- #829660# pundł +- [ˌn̩daːˌbuʃɻ̩ ˌpastɐksˌiːstʊˌxɑːruəɬʲ ˌdʒutːəˌbuʃɻ̩ ˌdʒutːɐksə ˈpundɫ̩] +- ńdá-bušŕ pas-taks(a)-ístu-hárual ǧutta-bušŕ ǧut(ta)-taksa pund(a)-ł +- 8 29 6 60 pound-PL +- 829,660 lb + +--- + +- nakasnala samńt kaubal +- [ˌnakɑsnɐlə ˈsamn̩t kɑʊvɐɬʲ] +- na-kas-na-la samń-t kauba-l +- one-COM-one-INS colour-GEN group-PL +- all sets of colours +::: + +:::aside +btw, `{!nakasnai}`, literally "anything and anything", means "everything". i forgot which language i stole that from, sorry. + +it can be shortened to `{!násna}`, and its derived forms `{!nakasnala}` "every" and `{!nakasnanua}` "always" can be shortened to `{!násná}` [(ending with a long vowel)]{.note} and `{!násnua}` respectively. +::: + +:::{.glosses .left} +- násnua álitkiðkasł dilwitł ippau +- [ˌnaːsnʊə ˈaːlɪtkɛθkɑsɫ̩ ˈdilwetɫ ipːɑʊ] +- nakasna(i)-nua álit-kið-kas-ł dilwi-t-ł ippau +- all-INTER neck-ring-COM sock-GEN-PL wear +- always wears collars and socks + +--- + +- ustaimł! panísat igisḿt ǧunaimkas pattal +- [ˈustɐɪmɫ̩ ‖ pɐˌniːsɐt ˌiʝɛsm̩t ˈdʒnɐimkɑs ˈpatːaɬʲ] +- ustai-m-ł panísa-t igis-ḿ-t ǧunai-m-kas patta-l +- magic-DEF-PL blue-GEN crystal-DEF-GEN rod-DEF-COM portal-PL +- magic! the blue crystal rod and portals + +--- + +- kalli talaskasł nai usu liččali ai +- [ˌkɑɫːe ˈtalɐskɑsɫ̩ ˌnæɪj‿ˈusʊ ˌlitːʃɐlɪj‿æɪ] +- kalli talas-kas-ł nai usu ličča-li ai +- three head-COM-PL one mind much-IN be +- there are three heads but usually one mind + +::: + +you may notice some discrepancies between these squiggles and the squiggles on the refsheet. ~~oops! i'll fix em tomorrow.~~ it wasn't quite "tomorrow" but it's done now. + +well bye diff --git a/posts/qt-refsheet/ref.webp b/posts/qt-refsheet/ref.webp new file mode 100644 index 0000000..4561abe Binary files /dev/null and b/posts/qt-refsheet/ref.webp differ diff --git a/posts/quorientation.md b/posts/quorientation.md index ed8084b..d40f526 100644 --- a/posts/quorientation.md +++ b/posts/quorientation.md @@ -1,16 +1,17 @@ --- date: 2024-03-14 title: quorientation -tags: [lántas, conlangs] +tags: [fursona, lántas, conlangs] conlang: laantas summary: | in my latest art, i put some text in lántas. here is approximately too much detail about that. +header-includes: ...
- +
@@ -40,7 +41,7 @@ you know! the thing! from the game!
well. from the fan translation
- +
- out of context, `{!patta}` means door. i suppose a portal would be a magic diff --git a/posts/quorientation/pic.webp b/posts/quorientation/pic.webp new file mode 100644 index 0000000..780230b Binary files /dev/null and b/posts/quorientation/pic.webp differ diff --git a/posts/quorientation/skip-some-floors.png b/posts/quorientation/skip-some-floors.png new file mode 100644 index 0000000..02e3623 Binary files /dev/null and b/posts/quorientation/skip-some-floors.png differ diff --git a/sources/cube.kra b/sources/cube.kra new file mode 100644 index 0000000..d95e7f3 Binary files /dev/null and b/sources/cube.kra differ diff --git a/sources/rainbow-quox/blends.png b/sources/rainbow-quox/blends.png new file mode 100644 index 0000000..8c9db40 Binary files /dev/null and b/sources/rainbow-quox/blends.png differ diff --git a/sources/rainbow-quox/dark.png b/sources/rainbow-quox/dark.png new file mode 100644 index 0000000..469bdba Binary files /dev/null and b/sources/rainbow-quox/dark.png differ diff --git a/sources/rainbow-quox/dark2.png b/sources/rainbow-quox/dark2.png new file mode 100644 index 0000000..162f009 Binary files /dev/null and b/sources/rainbow-quox/dark2.png differ diff --git a/sources/rainbow-quox/front.png b/sources/rainbow-quox/front.png new file mode 100644 index 0000000..fdfc4a0 Binary files /dev/null and b/sources/rainbow-quox/front.png differ diff --git a/sources/rainbow-quox/pieces1.kra b/sources/rainbow-quox/pieces1.kra new file mode 100644 index 0000000..95372be Binary files /dev/null and b/sources/rainbow-quox/pieces1.kra differ diff --git a/sources/rainbow-quox/pieces2.kra b/sources/rainbow-quox/pieces2.kra new file mode 100644 index 0000000..0aebab3 Binary files /dev/null and b/sources/rainbow-quox/pieces2.kra differ diff --git a/sources/rainbow-quox/quoxes1.kra b/sources/rainbow-quox/quoxes1.kra new file mode 100644 index 0000000..7388c3b Binary files /dev/null and b/sources/rainbow-quox/quoxes1.kra differ diff --git a/sources/rainbow-quox/quoxes1.png b/sources/rainbow-quox/quoxes1.png new file mode 100644 index 0000000..8d42de0 Binary files /dev/null and b/sources/rainbow-quox/quoxes1.png differ diff --git a/sources/rainbow-quox/red.png b/sources/rainbow-quox/red.png new file mode 100644 index 0000000..925d5a4 Binary files /dev/null and b/sources/rainbow-quox/red.png differ diff --git a/sources/rainbow-quox/relative.png b/sources/rainbow-quox/relative.png new file mode 100644 index 0000000..395e0bd Binary files /dev/null and b/sources/rainbow-quox/relative.png differ diff --git a/style/page.css b/style/page.css index 7394654..0eb0b8d 100644 --- a/style/page.css +++ b/style/page.css @@ -38,10 +38,9 @@ :root, body { margin: 0; padding: 0; } -main { - border-bottom: 2px dotted var(--fg); +main, footer { max-width: 50rem; } - max-width: 50em; +main { min-height: 100%; margin: 1em auto 0; padding: 0.5em 2em; @@ -63,10 +62,13 @@ header { header h1 { font-size: 200%; margin: 0; + font-weight: normal; + text-transform: uppercase; + letter-spacing: 0.4ch; } /* h1, h2, h3, h4, h5, h6 { */ -h1 { +main h1 { margin: 1em 0 0.25em; font-weight: normal; @@ -231,7 +233,7 @@ pre, :not(pre) > code { pre, :not(pre) > code { background: hsla(0deg 0% 00% / 30%); } } -:not(pre) > code { padding: 0 5px; } +:not(pre) > code { padding: 0 5px; white-space: nowrap; } pre { clear: both; @@ -260,16 +262,20 @@ pre { font-weight: normal; } -.gloss .abbr, .abbr-list dt { +.abbr, .abbr-list dt { font-variant: all-small-caps; } .scr { height: 1.5em; vertical-align: -40%; - margin-right: 0.5ex; - padding: 2px; - background: var(--light); +} + +@media (prefers-color-scheme: dark) { + .scr { + padding: 2px; + background: var(--light); + } } .gloss-split, .gloss-gloss { @@ -280,6 +286,10 @@ pre { height: 2em; } +.hugescr .scr { + height: 4em; +} + :is(.splash, .example) .scr { height: unset; display: block; @@ -344,15 +354,33 @@ blockquote { figure img { max-width: 100%; } -figure img:not(.scr) { +figure:not(.nobg, .hasborder) img:not(.scr) { border: 3px solid currentcolor; } +figure.nobg a img { + /* fake outline */ + filter: + drop-shadow(1px 1px 0 currentcolor) + drop-shadow(1px -1px 0 currentcolor) + drop-shadow(-1px 1px 0 currentcolor) + drop-shadow(-1px -1px 0 currentcolor) + drop-shadow(1px 0 0 currentcolor) + drop-shadow(-1px 0 0 currentcolor) + drop-shadow(0 1px 0 currentcolor) + drop-shadow(0 -1px 0 currentcolor) ; +} +figure.lightbg img { + background: var(--light); +} figure:not(.left) { text-align: center; } figure:not(.left) table { display: inline-table; } +.twocol-grid figure { + margin: 0; +} figure table { margin: 1em 0.5em; } @@ -376,6 +404,11 @@ figcaption { line-height: 125%; font-style: italic; margin: 0 auto; + text-align: center; + text-wrap: balance; +} +figcaption em { + font-style: normal; } :not(.floating) > figcaption { width: 75%; @@ -428,6 +461,7 @@ u u { footer { clear: both; + border-top: 2px dotted var(--fg); margin: 1.5em auto 3em; font-size: 80%; @@ -485,7 +519,7 @@ footer li + li::before { content: ' · '; } } blockquote { - max-width: 70%; + max-width: 85%; border-left: 1px solid black; padding-left: 1em; margin: auto; @@ -500,6 +534,15 @@ blockquote { font-style: italic; } +.banner { + font-size: 125%; + font-weight: bolder; + text-align: center; + text-wrap: balance; +} +.banner p:first-child::before { content: '☛ '; } +.banner p:last-child::after { content: ' ☚'; } + :is(h1, h2) .note { font-size: 75%; } @@ -596,6 +639,12 @@ aside.floating :last-child { margin-bottom: 0; } vertical-align: -0.1em; } +.bigemoji { + height: 2em; + width: 2em; + vertical-align: -0.2em; +} + .citation { font-size: 90%;