some posts
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
dist-newstyle
|
||||
_build
|
||||
_tmp
|
||||
.directory
|
||||
*~
|
||||
|
|
BIN
images/bub_flop.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 99 KiB |
BIN
images/panqt.png
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 98 KiB |
128
images/qt.svg
|
@ -1,128 +0,0 @@
|
|||
<?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>
|
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 509 KiB |
Before Width: | Height: | Size: 382 B |
BIN
images/quox.png
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 132 KiB |
|
@ -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
|
||||
...
|
||||
|
||||
<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}
|
|
@ -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
|
||||
...
|
||||
|
||||
<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] *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}
|
||||
|
||||
<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. 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
|
||||
|
||||
<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}
|
|
@ -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
|
||||
|
||||
<!-- 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. :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
|
274
posts-wip/rainbow-quox.md
Normal file
|
@ -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]
|
||||
<!-- TODO add this link!!! -->
|
||||
:::
|
||||
|
||||
# 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
|
||||
|
||||
{.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
|
||||
|
||||
{.expandable .lightbg}
|
||||
|
||||
now let's layer them back on top of each other with some css.
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<style>
|
||||
#container {
|
||||
width: 100%; position: relative;
|
||||
img { position: absolute; inset: 0; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id=container>
|
||||
<img src=outer.png> <img src=belly.png> <img src=eyes.png>
|
||||
<img src=tongues.png> <img src=collars.png> <img src=masks.png>
|
||||
<img src=socks.png> <img src=stripes.png> <img src=lines.png>
|
||||
</div>
|
||||
```
|
||||
|
||||
{.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?
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
well that's no good at all. i guess that warning was serious.
|
||||
|
||||
# ok what about blend modes
|
||||
|
||||
{.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
|
||||
|
||||
{.bigemoji .pixel} \
|
||||
|
||||
```svg
|
||||
<svg style="position: absolute">
|
||||
<filter id="fouter">
|
||||
<feFlood result="hue" flood-color="#57267e" />
|
||||
<feBlend in="hue" in2="SourceGraphic" mode="hue" result="res" />
|
||||
<!-- ↓ without this the background will also be filled in -->
|
||||
<feComposite in="res" in2="SourceGraphic" operator="in" />
|
||||
</filter>
|
||||
<!-- …and same for the others, with different flood-colors -->
|
||||
</svg>
|
||||
```
|
||||
|
||||
```css
|
||||
#outer { filter: url(#fouter); }
|
||||
/* …etc… */
|
||||
```
|
||||
|
||||
and…
|
||||
|
||||
{.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_:
|
||||
|
||||
{.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
|
||||
<div id=container>
|
||||
<!-- divs not images now. the images are all in the background properties -->
|
||||
<div class=part id=static></div>
|
||||
<div class=part id=spines></div>
|
||||
<div class=part id=stripes></div>
|
||||
<!-- etc… -->
|
||||
<div id=eye-shine></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
{.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: |
|
||||
<style>
|
||||
#relcolor {
|
||||
max-width: 20em; margin: auto;
|
||||
display: grid; grid-template-columns: 1fr 1fr; gap: .5em;
|
||||
font-weight: bold;
|
||||
--hi: #ea9aa1; --wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
#relcolor div {
|
||||
text-align: center; font-size: 125%;
|
||||
padding: .4em; border-radius: .5em;
|
||||
color: black;
|
||||
background: var(--bg);
|
||||
border: 4px solid oklch(from var(--bg) .25 75% h);
|
||||
}
|
||||
#hi { --bg: var(--hi); }
|
||||
#wow { --bg: var(--wow); }
|
||||
</style>
|
||||
...
|
||||
|
||||
<div id=relcolor>
|
||||
<div id=hi>\--hi</div>
|
||||
<div id=wow>\--wow</div>
|
||||
</div>
|
||||
|
||||
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 `<angle>`. 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:
|
||||
|
||||
{.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 <https://stackoverflow.com/a/47593315>. whatever
|
||||
- if so: use that to make palette permalinks
|
BIN
posts-wip/rainbow-quox/blends.avif
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
posts-wip/rainbow-quox/dark.avif
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
posts-wip/rainbow-quox/dark2.avif
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
posts-wip/rainbow-quox/front.avif
Normal file
After Width: | Height: | Size: 153 KiB |
BIN
posts-wip/rainbow-quox/pieces1.avif
Normal file
After Width: | Height: | Size: 418 KiB |
BIN
posts-wip/rainbow-quox/pieces2.avif
Normal file
After Width: | Height: | Size: 536 KiB |
BIN
posts-wip/rainbow-quox/quoxes1.avif
Normal file
After Width: | Height: | Size: 652 KiB |
BIN
posts-wip/rainbow-quox/red.avif
Normal file
After Width: | Height: | Size: 152 KiB |
BIN
posts-wip/rainbow-quox/relative.avif
Normal file
After Width: | Height: | Size: 210 KiB |
|
@ -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}
|
||||
{width=100%}
|
||||
<figure class=hasborder>
|
||||
<a href=https://gallery.niss.website/main/niss/2023-12-25-merr-crismas/>
|
||||
<img src=chrismas/1.webp>
|
||||
</a>
|
||||
</figure>
|
||||
|
||||
::: {.glosses .left}
|
||||
- þugusim ai
|
||||
|
@ -90,7 +94,11 @@ midwinter".
|
|||
- it crismas
|
||||
:::
|
||||
|
||||
{width=100%}
|
||||
<figure class=hasborder>
|
||||
<a href=https://gallery.niss.website/main/niss/2023-12-25-merr-crismas/>
|
||||
<img src=chrismas/2.webp>
|
||||
</a>
|
||||
</figure>
|
||||
|
||||
::: {.glosses .left}
|
||||
- ufi þugusinhari
|
||||
|
|
BIN
posts/chrismas/1.webp
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
posts/chrismas/2.webp
Normal file
After Width: | Height: | Size: 42 KiB |
|
@ -6,7 +6,7 @@ summary: >
|
|||
i redesigned my personal website. it was a bit of an ordeal.
|
||||
...
|
||||
|
||||
{.floating .right}
|
||||
{.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:
|
||||
|
||||
|
|
BIN
posts/cube/cube.webp
Normal file
After Width: | Height: | Size: 301 KiB |
129
posts/first-person-pronouns.md
Normal file
|
@ -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 <abbr class=abbr title=comitative>COM</abbr>, 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: |
|
||||
<style>
|
||||
.ptable, .vtable {
|
||||
text-align: center;
|
||||
th:nth-child(3) {
|
||||
background: var(--fg);
|
||||
color: var(--bg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
...
|
||||
|
||||
<table class=ptable>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<th> <abbr class=abbr title='first person singular'>1SG</abbr>
|
||||
<th> <abbr class=abbr title='first person system-plural'>1SPL</abbr>
|
||||
<th> <abbr class=abbr title='first person inclusive plural'>1EPL</abbr>
|
||||
<tbody><tr>
|
||||
<th> <abbr class=abbr title=nominative>NOM</abbr>
|
||||
<td> `{!ká}`
|
||||
<td> `{!kál}`
|
||||
<td> `{!til}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=genitive>GEN</abbr>
|
||||
<td> `{!kat}`
|
||||
<td> `{!katł}`
|
||||
<td> `{!tial}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=comitative>COM</abbr>
|
||||
<td> `{!kakas}`
|
||||
<td> `{!kaksł}`
|
||||
<td> `{!tiksł}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=caritive>CAR</abbr>
|
||||
<td> `{!kassa}`
|
||||
<td> `{!kassal}`
|
||||
<td> `{!tissal}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=instrumental>INS</abbr>
|
||||
<td> `{!kala}`
|
||||
<td> `{!kalal}`
|
||||
<td> `{!tilla}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=essive>ESS</abbr>
|
||||
<td> `{!kugu}`
|
||||
<td> `{!kugul}`
|
||||
<td> `{!tigul}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=translative>TRA</abbr>
|
||||
<td> `{!kasti}`
|
||||
<td> `{!kastil}`
|
||||
<td> `{!tistil}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=exessive>EXE</abbr>
|
||||
<td> `{!kaču}`
|
||||
<td> `{!kačul}`
|
||||
<td> `{!tičul}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title='locative stem'>LOC</abbr>
|
||||
<td> `{!ká–}`
|
||||
<td> `{!ká–l}`
|
||||
<td> `{!tí–l}`
|
||||
</table>
|
||||
|
||||
|
||||
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áš}` <br> `{#–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
|
||||
|
||||
<table class=vtable>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<th> <abbr class=abbr title='first person singular'>1SG</abbr>
|
||||
<th> <abbr class=abbr title='first person system-plural'>1SPL</abbr>
|
||||
<th> <abbr class=abbr title='first person inclusive plural'>1EPL</abbr>
|
||||
<tbody><tr>
|
||||
<th> <abbr class=abbr title=subject>SBJ</abbr>
|
||||
<td> `{!–na}`
|
||||
<td> `{!–káš}`
|
||||
<td> `{!–náš}`
|
||||
<tr>
|
||||
<th> <abbr class=abbr title=object>OBJ</abbr>
|
||||
<td> `{!–du}`
|
||||
<td> `{!–kúš}`
|
||||
<td> `{!–dúš}`
|
||||
</table>
|
62
posts/goodbye-cohost.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
title: goodbye cohost
|
||||
tags: [misc]
|
||||
date: 2024-10-01
|
||||
summary: thanks for being a website.
|
||||
header-includes: |
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: PressStart;
|
||||
src: url(goodbye-cohost/PressStart2P-Regular.woff2) format('woff2'),
|
||||
url(goodbye-cohost/PressStart2P-Regular.ttf) format('ttf');
|
||||
}
|
||||
.screen {
|
||||
font-family: PressStart, monospace;
|
||||
line-height: 2em;
|
||||
height: 20lh;
|
||||
width: 28ch;
|
||||
background: black;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
margin: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
.screen + :is(.screen, audio) { margin-top: 1lh; }
|
||||
.green { color: #0f0; }
|
||||
.red { color: #f00; }
|
||||
.cyan { color: #0df; }
|
||||
.yellow { color: #ff0; }
|
||||
.center { width: 7ch; display: block; margin: .5lh auto; }
|
||||
audio {
|
||||
display: block;
|
||||
font-family: PressStart;
|
||||
width: calc(28ch + 10px);
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
...
|
||||
|
||||
```{=html}
|
||||
<audio src=goodbye-cohost/hiscore.mp3 controls loop></audio>
|
||||
<div class=screen> <span class=green>HIGH SCORE</span>
|
||||
6969420 <span class=yellow>6969420</span>
|
||||
|
||||
<span class=red>CONGRATURATIONS !!</span>
|
||||
|
||||
<span class=cyan>NOW YOU SAVE EGGBUG
|
||||
AND
|
||||
THE ADVENTURE IS OVER
|
||||
|
||||
THANK YOU
|
||||
FROM
|
||||
WEB SITE jkap
|
||||
vogon
|
||||
GRAPHIC DESIGN aidan
|
||||
MODERATION kaara
|
||||
AND</span>
|
||||
AMUSEMENT CREATER
|
||||
<img src=goodbye-cohost/cohost.svg class=center>
|
||||
</div>
|
||||
```
|
||||
|
||||
thanks for being a website.
|
BIN
posts/goodbye-cohost/PressStart2P-Regular.ttf
Normal file
BIN
posts/goodbye-cohost/PressStart2P-Regular.woff2
Normal file
1
posts/goodbye-cohost/cohost.svg
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
posts/goodbye-cohost/hiscore.mp3
Normal file
92
posts/qt-refsheet.md
Normal file
|
@ -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
|
||||
<a href=https://gallery.niss.website/main/niss/2024-11-26-qt-ref-2024/>
|
||||

|
||||
</a>
|
||||
:::
|
||||
|
||||
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
|
BIN
posts/qt-refsheet/ref.webp
Normal file
After Width: | Height: | Size: 490 KiB |
|
@ -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: <base href=quorientation>
|
||||
...
|
||||
|
||||
<figure>
|
||||
<a href=http://gallery.niss.website/main/niss/2024-03-14-quorientation/>
|
||||
<img src=../images/quorientation.png>
|
||||
<img src=quorientation/pic.webp>
|
||||
</a>
|
||||
</figure>
|
||||
|
||||
|
@ -40,7 +41,7 @@ you know! the thing! from the game!
|
|||
|
||||
<figure class='floating right'>
|
||||
<figcaption> well. from the fan translation </figcaption>
|
||||
<img src=../images/skip-some-floors.png class=pixel alt=''>
|
||||
<img src=quorientation/skip-some-floors.png class=pixel alt=''>
|
||||
</figure>
|
||||
|
||||
- out of context, `{!patta}` means door. i suppose a portal would be a magic
|
||||
|
|
BIN
posts/quorientation/pic.webp
Normal file
After Width: | Height: | Size: 372 KiB |
BIN
posts/quorientation/skip-some-floors.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
sources/cube.kra
Normal file
BIN
sources/rainbow-quox/blends.png
Normal file
After Width: | Height: | Size: 397 KiB |
BIN
sources/rainbow-quox/dark.png
Normal file
After Width: | Height: | Size: 320 KiB |
BIN
sources/rainbow-quox/dark2.png
Normal file
After Width: | Height: | Size: 302 KiB |
BIN
sources/rainbow-quox/front.png
Normal file
After Width: | Height: | Size: 500 KiB |
BIN
sources/rainbow-quox/pieces1.kra
Normal file
BIN
sources/rainbow-quox/pieces2.kra
Normal file
BIN
sources/rainbow-quox/quoxes1.kra
Normal file
BIN
sources/rainbow-quox/quoxes1.png
Normal file
After Width: | Height: | Size: 6.4 MiB |
BIN
sources/rainbow-quox/red.png
Normal file
After Width: | Height: | Size: 468 KiB |
BIN
sources/rainbow-quox/relative.png
Normal file
After Width: | Height: | Size: 1 MiB |
|
@ -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,17 +262,21 @@ 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;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.scr {
|
||||
padding: 2px;
|
||||
background: var(--light);
|
||||
}
|
||||
}
|
||||
|
||||
.gloss-split, .gloss-gloss {
|
||||
font-size: 80%;
|
||||
|
@ -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%;
|
||||
|
|