Compare commits
27 Commits
partially_
...
b2216f7574
| Author | SHA1 | Date | |
|---|---|---|---|
| b2216f7574 | |||
| 9ec99a94eb | |||
| c994f1b1af | |||
| febe356575 | |||
| 0df6ce49fe | |||
| 87763fad40 | |||
| 5054441625 | |||
| 3dcebe5297 | |||
| f55dd236b6 | |||
| f4b99067d4 | |||
| a990809e21 | |||
| f567172099 | |||
| ee4add2fee | |||
| ab700c12b1 | |||
| cad202551b | |||
| 4e7825cb2b | |||
| 6ef3392aa0 | |||
| b89b831983 | |||
| a06c5854c8 | |||
| 8ccdfd8ab2 | |||
| 3c5bb127e2 | |||
| 8fa7acbdf1 | |||
| 664b336a48 | |||
| 70ac3e3633 | |||
| 049624a840 | |||
| 85454fda79 | |||
| 30c4d4b28c |
1
.gitignore
vendored
@@ -9,7 +9,6 @@ build-ninja
|
||||
*.swi
|
||||
*.swj
|
||||
*.swk
|
||||
*.png
|
||||
.*.un~
|
||||
callgrind*
|
||||
.stfolder
|
||||
|
||||
@@ -98,7 +98,8 @@
|
||||
#wasm3
|
||||
|
||||
clang cmake
|
||||
(rust-bin.stable.latest.default.override { targets = [ "wasm32-wasi" ]; })
|
||||
cargo cargo-flamegraph
|
||||
#(rust-bin.stable.latest.default.override { targets = [ "wasm32-wasi" ]; })
|
||||
#stack (haskellPackages.ghcWithPackages (p: [p.parallel]))
|
||||
koka
|
||||
pkgs_old.emscripten
|
||||
|
||||
@@ -6,6 +6,10 @@ build = "build.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
[profile.bench]
|
||||
debug = true
|
||||
|
||||
[dependencies]
|
||||
lalrpop-util = {version="0.19.7", features=["lexer"]}
|
||||
regex = "1"
|
||||
|
||||
@@ -19,7 +19,7 @@ fn main() {
|
||||
let (bctx, marked) = mark(Rc::clone(&parsed_input),bctx);
|
||||
let unvaled = marked.unval().unwrap();
|
||||
println!("Parsed unvaled that is {}", unvaled);
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled).unwrap();
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled, true).unwrap();
|
||||
let result = eval(root_env(), parsed_input);
|
||||
println!("Result is {} - {:?}", result, result);
|
||||
}
|
||||
|
||||
797
kr/src/pe_ast.rs
@@ -28,7 +28,7 @@ fn eval_test<T: Into<Form>>(also_pe: bool, gram: &grammar::TermParser, e: &Rc<Fo
|
||||
let (bctx, dctx) = new_base_ctxs();
|
||||
let (bctx, marked) = mark(parsed,bctx);
|
||||
let unvaled = marked.unval().unwrap();
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled).unwrap();
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled, true).unwrap();
|
||||
let (bctx, marked_basic_result) = mark(basic_result,bctx);
|
||||
println!("Final PE {}", ped);
|
||||
println!("wanted {}", marked_basic_result);
|
||||
@@ -41,7 +41,7 @@ fn partial_eval_test(gram: &grammar::TermParser, code: &str, expected: &str) {
|
||||
let (bctx, dctx) = new_base_ctxs();
|
||||
let (bctx, marked) = mark(parsed,bctx);
|
||||
let unvaled = marked.unval().unwrap();
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled).unwrap();
|
||||
let (bctx, ped) = partial_eval(bctx, dctx, unvaled, true).unwrap();
|
||||
println!("Final PE {}", ped);
|
||||
println!("wanted {}", expected);
|
||||
assert_eq!(format!("{}", ped), expected);
|
||||
@@ -50,7 +50,15 @@ fn partial_eval_test(gram: &grammar::TermParser, code: &str, expected: &str) {
|
||||
fn basic_pe_test() {
|
||||
let g = grammar::TermParser::new();
|
||||
partial_eval_test(&g, "(+ 2 (car (cons 4 '(1 2))))", "6");
|
||||
partial_eval_test(&g, "(vau 0 p (+ 1 2))", "NeededIds { heads: {}, tails: {}, body_stopped: {}, if_stopped: {} }#[None/None/EnvID(1)/0/[]/Some(\"p\")/3]");
|
||||
partial_eval_test(&g, "(vau 0 p (+ 1 2))", "NeedsNone#[None/None/EnvID(1)/0/[]/Some(\"p\")/3]");
|
||||
|
||||
partial_eval_test(&g, "(vau de p (+ (eval (car p) de) (eval (car (cdr p)) de)))", "NeedsNone#[None/Some(\"de\")/EnvID(1)/0/[]/Some(\"p\")/NeedsH{EnvID(1)}#{<+0> Some(\"p\")(EnvID(1)0truetrue) Some(\"p\")(EnvID(1)1truetrue)}]");
|
||||
|
||||
partial_eval_test(&g, "(vau de p (eval '(+ a 2) (cons (cons 'a (eval (car p) de))
|
||||
((vau de p de)))))", "NeedsNone#[None/Some(\"de\")/EnvID(1)/0/[]/Some(\"p\")/NeedsH{EnvID(1)}#{<+0> Some(\"a\")(EnvID(1)0truetrue) 2}]");
|
||||
//partial_eval_test(&g, "(vau de p (eval (+ a b) (cons (cons 'a (eval (car p) de))
|
||||
// (cons (cons 'b (eval (car (cdr p)) de))
|
||||
// de))))", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -116,16 +124,16 @@ static LET: Lazy<String> = Lazy::new(|| {
|
||||
fn let_pe_test() {
|
||||
let g = grammar::TermParser::new();
|
||||
partial_eval_test(&g, &format!("{} (let1 a 2 (+ a (car (cons 4 '(1 2)))))", *LET), "6");
|
||||
partial_eval_test(&g, &format!("{} (let1 a 2 (vau 0 p (+ 1 a)))", *LET),"NeededIds { heads: {}, tails: {}, body_stopped: {}, if_stopped: {} }#[None/None/EnvID(3)/0/[]/Some(\"p\")/3]");
|
||||
partial_eval_test(&g, &format!("{} (let1 a 2 (vau 0 p (+ 1 a)))", *LET),"NeedsNone#[None/None/EnvID(3)/0/[]/Some(\"p\")/3]");
|
||||
partial_eval_test(&g, &format!("{}
|
||||
!(let1 a 2)
|
||||
(vau 0 p (+ 1 a))
|
||||
", *LET), "NeededIds { heads: {}, tails: {}, body_stopped: {}, if_stopped: {} }#[None/None/EnvID(3)/0/[]/Some(\"p\")/3]");
|
||||
", *LET), "NeedsNone#[None/None/EnvID(3)/0/[]/Some(\"p\")/3]");
|
||||
partial_eval_test(&g, &format!("{}
|
||||
!(let1 a 2)
|
||||
!(let1 b 5)
|
||||
(vau 0 p (+ b a))
|
||||
", *LET), "NeededIds { heads: {}, tails: {}, body_stopped: {}, if_stopped: {} }#[None/None/EnvID(3)/0/[]/Some(\"p\")/7]");
|
||||
", *LET), "NeedsNone#[None/None/EnvID(3)/0/[]/Some(\"p\")/7]");
|
||||
/*
|
||||
partial_eval_test(&g, &format!("{}
|
||||
(vau 0 p
|
||||
|
||||
BIN
website/Inter.var.woff2
Normal file
BIN
website/JetBrainsMono-Regular.woff2
Normal file
230
website/LICENSE
@@ -1,3 +1,204 @@
|
||||
|
||||
|
||||
###########################
|
||||
For Inter (the font):
|
||||
###########################
|
||||
|
||||
Copyright (c) 2016-2020 The Inter Project Authors.
|
||||
"Inter" is trademark of Rasmus Andersson.
|
||||
https://github.com/rsms/inter
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION AND CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
|
||||
###########################
|
||||
For JetBrains Mono (the font):
|
||||
###########################
|
||||
|
||||
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
|
||||
###########################
|
||||
For Recursive (the font):
|
||||
###########################
|
||||
@@ -161,3 +362,32 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
|
||||
#########################################
|
||||
For RemarkJS (the presentation framework)
|
||||
#########################################
|
||||
|
||||
Copyright (c) 2011-2013 Ole Petter Bang <olepbang@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
BIN
website/images/Kraken_Call_PE_Semantics.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
website/images/Kraken_NonCall_PE_Semantics.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
website/images/Kraken_aux_helpers.png
Normal file
|
After Width: | Height: | Size: 213 KiB |
BIN
website/images/Kraken_aux_helpers2.png
Normal file
|
After Width: | Height: | Size: 139 KiB |
BIN
website/images/Kraken_aux_helpers3.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
website/images/Kraken_pe_primitives.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
website/images/cfold_table.csv_.png
Normal file
|
After Width: | Height: | Size: 222 KiB |
BIN
website/images/cfold_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
website/images/deriv_table.csv_.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
website/images/deriv_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
website/images/fib_table.csv_.png
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
website/images/fib_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 389 KiB |
BIN
website/images/lisp_timeline_screenshot.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
website/images/lisp_timeline_screenshot_edited.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
website/images/lisp_timeline_screenshot_edited.xcf
Normal file
BIN
website/images/nqueens_table.csv_.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
website/images/nqueens_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 262 KiB |
BIN
website/images/overview.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
website/images/rbtree_table.csv_.png
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
website/images/rbtree_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
website/images/slow_cfold_table.csv_.png
Normal file
|
After Width: | Height: | Size: 247 KiB |
BIN
website/images/slow_cfold_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
website/images/slow_deriv_table.csv_.png
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
website/images/slow_deriv_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 260 KiB |
BIN
website/images/slow_fib_table.csv_.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
website/images/slow_fib_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 382 KiB |
BIN
website/images/slow_ish_rbtree_table.csv_.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
website/images/slow_ish_rbtree_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
website/images/slow_nqueens_table.csv_.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
BIN
website/images/slow_nqueens_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 284 KiB |
BIN
website/images/slow_rbtree_table.csv_.png
Normal file
|
After Width: | Height: | Size: 348 KiB |
BIN
website/images/slow_rbtree_table.csv_log.png
Normal file
|
After Width: | Height: | Size: 359 KiB |
@@ -2,93 +2,13 @@
|
||||
<html lang="en-us">
|
||||
<meta charset="UTF-8">
|
||||
<head>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Recursive';
|
||||
font-style: oblique 0deg 15deg;
|
||||
font-weight: 300 1000;
|
||||
font-display: swap;
|
||||
src: url(./Recursive.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
:root {
|
||||
--rec-wght: 400;
|
||||
--rec-slnt: 0;
|
||||
--rec-mono: 0;
|
||||
--rec-casl: 0;
|
||||
--rec-csrv: 0;
|
||||
}
|
||||
* {
|
||||
font-variation-settings: "wght" var(--rec-wght),
|
||||
"slnt" var(--rec-slnt),
|
||||
"MONO" var(--rec-mono),
|
||||
"CASL" var(--rec-casl),
|
||||
"CRSV" var(--rec-csrv);
|
||||
}
|
||||
body {
|
||||
max-width: 45em;
|
||||
margin: 1em auto;
|
||||
padding: 0 .62em;
|
||||
font: 1.2em/1.62 'Recursive', sans-serif;
|
||||
}
|
||||
h1, h2, h3, h4 {
|
||||
line-height:1.2;
|
||||
--rec-wght: 700;
|
||||
--rec-casl: 1;
|
||||
--rec-crsv: 1;
|
||||
}
|
||||
h1 {
|
||||
line-height:0.7;
|
||||
font-size: 4em;
|
||||
--rec-wght: 900;
|
||||
--rec-slnt: -15;
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 0.4rem;
|
||||
//border-bottom: 0.08em solid;
|
||||
//border-left: 0.1em solid;
|
||||
//display: inline-block;
|
||||
}
|
||||
h2 { font-size: 3em; }
|
||||
h3 { font-size: 1.5em; }
|
||||
h4 { font-size: 1.2em; }
|
||||
i { --rec-slnt: -14; }
|
||||
b { --rec-wght: 600; }
|
||||
.run_container { position: relative; }
|
||||
.editor {
|
||||
font-family: 'Recursive', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||
height: 7em;
|
||||
letter-spacing: normal;
|
||||
tab-size: 4;
|
||||
}
|
||||
.output {
|
||||
margin-block-start: 1rem;
|
||||
font-family: 'Recursive', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
tab-size: 4;
|
||||
height: 5em;
|
||||
width: 100%;
|
||||
}
|
||||
.run_button {
|
||||
font-family: 'Recursive', sans-serif;
|
||||
font-size: 1em;
|
||||
--rec-wght: 900;
|
||||
--rec-slnt: -15;
|
||||
--rec-casl: 1;
|
||||
--rec-crsv: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
<!--<link id="theme" rel="stylesheet" type="text/css" href="slick.css"/>-->
|
||||
<link id="theme" rel="stylesheet" type="text/css" href="recursive.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<header><h1>Kraken</h1></header>
|
||||
<i>FOSS Fexprs: <a title="Kraken on GitHub" href="https://github.com/limvot/kraken">https://github.com/limvot/kraken</a></i>
|
||||
<!--<button onclick="toggleTheme()" style="float: right;">Swap Theme</button>-->
|
||||
<br>
|
||||
<h3>Demo:</h3>
|
||||
<div class="run_container">
|
||||
@@ -98,45 +18,32 @@
|
||||
(println "Math works:" (+ 1 2))
|
||||
</div>
|
||||
<textarea class="output" id="hello_output">Output will appear here</textarea>
|
||||
<button class="run_button" onclick="executeKraken(hello_editor_jar.toString(), 'hello_output')"><b>Run</b></button> <br>
|
||||
<button class="run_button" onclick="executeKraken(hello_editor_jar.toString(), 'hello_output')">Run</button> <br>
|
||||
</div>
|
||||
<a name="concept"/>
|
||||
<h3>Concept:</h3>
|
||||
<ul>
|
||||
<li> Minimal, close to the metal Kernel/Scheme (operate on words, bytes, arrays) as AST / core language, with Kernel/Vau calculus inspiration oblivating the need for non-reader macros (<a title="Kernel/Vau calculus thesis" href="https://web.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf">Kernel/Vau calculus thesis</a>)
|
||||
<li> Full Context-free (and eventually, context sensitive) reader macros using FUN-GLL (<a title="fun-gll paper" href="https://www.sciencedirect.com/science/article/pii/S2590118420300058">FUN-GLL paper</a>) to extend language's syntax dynamically
|
||||
<li> Implement Type Systems as Macros (but using Vaus instead of macros) (<a title="type systems as macros paper 1" href="http://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf">paper, up to System Fω</a>) (<a title="type systems as macros paper 2" href="https://www.ccs.neu.edu/home/stchang/pubs/cbtb-popl2020.pdf">second paper, up to dependent types</a>)
|
||||
<li> Use above "type systems as vaus" to create richer language and embed entire other programming languages (syntax, semantics, and type system) for flawless interop/FFI (C, Go, Lua, JS, etc)
|
||||
<li> File is interpreted, and then if "main" exists it is compiled, spidering backwards to referenced functions and data (Allows interpreted code to do metaprogramming, dependency resolution, generate code, etc, which is then compiled)
|
||||
<li> Regionalized Value State Dependence Graph as backend-IR, enabling simpler implementations of powerful optimizations (<a title="RSVDG paper" href="https://arxiv.org/pdf/1912.05036.pdf">RSVDG paper</a>) so that embedded languages have good performance when compiled with little code
|
||||
<li> Minimal, purely functional Kernel/Scheme as core language, with Kernel/Vau calculus inspiration oblivating the need for non-reader macros (<a title="Kernel/Vau calculus thesis" href="https://web.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf">Kernel/Vau calculus thesis</a>)
|
||||
<li> Partial evaluation to make fexprs fast (my PhD research! First paper on <a href="https://arxiv.org/abs/2303.12254">arXiv</a>)
|
||||
<li> Implement Type Systems as Macros (but using Fexprs instead of macros) (<a title="type systems as macros paper 1" href="http://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf">paper, up to System Fω</a>) (<a title="type systems as macros paper 2" href="https://www.ccs.neu.edu/home/stchang/pubs/cbtb-popl2020.pdf">second paper, up to dependent types</a>)
|
||||
<li> Use fexprs to bootstrap more complex features, like delimited continuations
|
||||
<li> Use above "type systems as fexprs" to add types and create a statically-typed language on top (with Algebraic Effects using the underlying delimited continuations, etc)
|
||||
</ul>
|
||||
<a name="about"/>
|
||||
<h3> About:</h3>
|
||||
<p> Currently, I am bootstrapping this new core Lisp out of my prior compiler for my programming language, Kraken. I have implemented the first version of the FUN-GLL algorithm and have working vaus and context-free reader macros.
|
||||
<p> The general flow is that the input files will be executed with the core Lisp interpreter, and if there is a "main" symbol defined the compiler emits C code for that function & all other functions & data that it references. In this way the language supports very powerful meta-programming at compile time, including adding syntax to the language, arbitrary computation, and importing other files, and then compiles into a static executable.
|
||||
<p> Below are a few examples of using the vau / live grammar modification / context-free reader macros to implement basic methods as well as embed the BF language into the core Lisp. The core Lisp implementation has been compiled to WebAssembly and should be able to run in your browser. Feel free to make edits and play around below.
|
||||
<br>
|
||||
Note that the current implementation is inefficient, and sometimes has problems running in phone web browsers.
|
||||
<a name="hello_example"/>
|
||||
<a name="vau_core"/>
|
||||
<p>This is my 3rd run at this Lisp concept, with Partial Evaluation to make fexprs fast forming the core of my current PhD research. <a href="https://miloignis.room409.xyz/">(tiny personal PhD website here)</a></p>
|
||||
<h4>Vau/Kernel as simple core:</h4>
|
||||
By constructing our core language on a very simple Vau/Kernel base, we can keep the base truely tiny, and build up normal Lisp functions and programming language features in the language itself. This should help implement other programming languages concisely, and will hopefully make optimization easier and more broadly applicable.
|
||||
<br>
|
||||
Below is the current prelude that adds quoting, quasiquoting, syntax for arrays and quoting/quasiquoting, do, if, let, and even lambda itself!
|
||||
<a name="next_steps"/>
|
||||
<h3>Next Steps</h3>
|
||||
<ul>
|
||||
<li> Implement persistent functional data structures
|
||||
<ul>
|
||||
<li> Hash Array-Mapped Trie (HAMT) / Relaxed Radix Balance Tree (RRB-Tree)
|
||||
<li> Hash Map based on the above
|
||||
<li> Hash Set based on the above
|
||||
<li> ✔ RB-Tree
|
||||
<li> ☐ Hash Array-Mapped Trie (HAMT) / Relaxed Radix Balance Tree (RRB-Tree)
|
||||
<li> ☐ Hash Map based on the above
|
||||
<li> ☐ Hash Set based on the above
|
||||
</ul>
|
||||
<li> Prototype Type Systems as Macros, may require macro system rewrite/upgrade
|
||||
<li> Sketch out Kraken language on top of core Lisp, includes basic Hindley-Milner type system implemented with Macros and above data structures
|
||||
<li> Sketch out Kraken language on top of core Lisp, includes basic Hindley-Milner type system
|
||||
<li> Re-self-host using functional approach in above Kraken language
|
||||
<li> Use Type System Macros to implement automatic transient creation on HAMT/RBB-Tree as an optimization
|
||||
<li> Implement RVSDG IR and develop best bang-for-buck optimizations using it
|
||||
</ul>
|
||||
|
||||
<link rel="stylesheet" href="./default.min.css">
|
||||
@@ -165,6 +72,14 @@ Note that the current implementation is inefficient, and sometimes has problems
|
||||
document.getElementById(new_output_name).value = "running...\n";
|
||||
Module.callMain(["-C", code]);
|
||||
}
|
||||
function toggleTheme() {
|
||||
let theme = document.getElementById('theme')
|
||||
if (theme.getAttribute("href") == "recursive.css") {
|
||||
theme.setAttribute("href", "slick.css");
|
||||
} else {
|
||||
theme.setAttribute("href", "recursive.css");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="k_prime.js"></script>
|
||||
</body>
|
||||
|
||||
754
website/presentation.html
Normal file
@@ -0,0 +1,754 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Kraken Quals Presentation</title>
|
||||
<link id="theme" rel="stylesheet" type="text/css" href="recursive.css"/>
|
||||
<!--<link id="theme" rel="stylesheet" type="text/css" href="slick.css"/>-->
|
||||
<link href="favicon.png" rel="icon" type="image/png"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<style type="text/css">
|
||||
body { max-width: unset; }
|
||||
.title > h1 {
|
||||
font-size: 4em;
|
||||
line-height:1;
|
||||
}
|
||||
h1 {
|
||||
line-height:1;
|
||||
|
||||
--rec-wght: 700;
|
||||
//--rec-slnt: -0;
|
||||
--rec-casl: 0.40;
|
||||
}
|
||||
.pull-left > * {
|
||||
float: left;
|
||||
width: 48%;
|
||||
}
|
||||
.pull-right > * {
|
||||
float: right;
|
||||
width: 48%;
|
||||
}
|
||||
.fullWidthImg > * { width: 95%; }
|
||||
.rerun_container { position: relative; }
|
||||
.mathSize9 { font-size: 0.9em; }
|
||||
.mathSize8 { font-size: 0.8em; }
|
||||
.mathSize6 { font-size: 0.6em; }
|
||||
</style>
|
||||
</head>
|
||||
<body onload="loadEverything();">
|
||||
<textarea id="source">
|
||||
|
||||
class: center, middle, title
|
||||
|
||||
# Kraken
|
||||
|
||||
_Fexprs are a better foundation for functional Lisps_
|
||||
|
||||
---
|
||||
|
||||
# Agenda
|
||||
|
||||
1. Lisp Background
|
||||
2. Macro and Fexpr comparison
|
||||
3. Fexpr problems
|
||||
4. Past Work: Practical compilation of fexprs using partial evaluation
|
||||
1. Kraken Language
|
||||
2. Partial Evalaution
|
||||
3. Optimizations
|
||||
5. Current & Future Work: Scheme & the more generic re-do, Delimited Continuations, Automatic Differientation, Type Systems
|
||||
---
|
||||
class: center, middle, title
|
||||
# Macros and Fexprs
|
||||
|
||||
_Lisp Background_
|
||||
---
|
||||
# Background: Lisp
|
||||
|
||||
Essentially every non-atomic expression is a parentheses delimited list.
|
||||
This is true for:
|
||||
<pre><code class="remark_code">(+ 1 2) ; function calls, evaluates to 3
|
||||
|
||||
(or a b) ; macro invocations, expands to
|
||||
; (let ((t a)) (if t t b))
|
||||
|
||||
(if false (+ 1 2) (- 1 2)) ; special forms like if
|
||||
</code></pre>
|
||||
|
||||
---
|
||||
# Background: Lisp
|
||||
|
||||
One of the key hallmarks of Lisp is macros
|
||||
|
||||
<pre><code class="remark_code">(or a b)
|
||||
</code></pre>
|
||||
becomes
|
||||
<pre><code class="remark_code">(let ((temp a))
|
||||
(if temp
|
||||
temp
|
||||
b))
|
||||
</code></pre>
|
||||
---
|
||||
# Background: Lisp Macros
|
||||
|
||||
Procedure like:
|
||||
<pre><code class="remark_code">(define-maco (or . body)
|
||||
(cond
|
||||
((nil? (cdr body)) (car body))
|
||||
(else (list 'let (list (list 'temp (car body)))
|
||||
(list 'if 'temp 'temp (car (cdr body)))))))
|
||||
</code></pre>
|
||||
Pattern matching:
|
||||
<pre><code class="remark_code">(letrec-syntax
|
||||
((or (syntax-rules ()
|
||||
((or a) a)
|
||||
((or a b)
|
||||
(let ((temp a))
|
||||
(if temp
|
||||
temp
|
||||
b)))))))
|
||||
</code></pre>
|
||||
---
|
||||
# Background: Lisp Macros
|
||||
As we've mentioned, in Scheme _or_ is a macro expanding
|
||||
<pre><code class="remark_code">(or a b)
|
||||
</code></pre>
|
||||
to
|
||||
<pre><code class="remark_code">(let ((temp a)) (if temp temp b))
|
||||
</code></pre>
|
||||
|
||||
So passing it to a higher-order function doesn't work, you have to wrap it in a function:
|
||||
<pre><code class="remark_code">> (fold or #f (list #t #f))
|
||||
Exception: invalid syntax and
|
||||
</code></pre>
|
||||
<pre><code class="remark_code">> (fold (lambda (a b) (or a b)) #f (list #t #f))
|
||||
#t
|
||||
</code></pre>
|
||||
---
|
||||
# Background: Fexprs
|
||||
|
||||
Something of a combo between the two - direct style, but naturally hygienic by default.
|
||||
<pre><code class="remark_code">(vau de (a b) (let ((temp (eval a de)))
|
||||
(if temp
|
||||
temp
|
||||
(eval b de))))
|
||||
</code></pre>
|
||||
But in Kraken, _or_ is a combiner (an operative!), so it's first-class
|
||||
So it's perfectly legal to pass to a higher-order combiner:
|
||||
<pre><code class="remark_code">> (foldl or false (array true false))
|
||||
true
|
||||
</code></pre>
|
||||
---
|
||||
# Background: Fexprs in Lisp
|
||||
|
||||
- 1960s - In earliest Lisps
|
||||
- 1980 - Argument that they shoudln't be included due to inability for static analysis to fix optimization problems (Kent Pitman, "Special Forms in Lisp")
|
||||
- 1998 - Adding fexprs to lambda calculus produces a trivial theory (Mitchell Wand, "The Theory of Fexprs is Trivial")
|
||||
- 2010 - Fexprs are not trivial with internal syntax, make sense with lexical scoping (John Shutt, "Fexprs as the basis of Lisp function application or $ vau: the ultimate abstraction", also earlier papers)
|
||||
---
|
||||
(from Wikipedia)
|
||||
.fullWidthImg[]
|
||||
---
|
||||
(from Wikipedia)
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Background: Fexprs - detail
|
||||
|
||||
Ok, Fexprs are calls to combiners - combiners are either applicatives or operatives.
|
||||
Combiners are introduced with _vau_ and take an extra parameter (here called _dynamic_env_, earlier called _de_) which is the dynamic environment.
|
||||
<pre><code class="remark_code">(vau dynamicEnv (normalParam1 normalParam2) (body of combiner))
|
||||
</code></pre>
|
||||
--
|
||||
Lisps, as well as Kraken, have an _eval_ function.
|
||||
This function takes in code as a data structure, and in R5RS Scheme an "environment specifier", and in Kraken, a full environment (like what is passed as _dynamicEnv_).
|
||||
<pre><code class="remark_code">(eval some_code an_environment)
|
||||
---
|
||||
# Pros and Cons
|
||||
**Pros:**
|
||||
1. Vau/Combiners unify and make first class functions, macros, and built-in forms in a single simple system
|
||||
2. They are also much simpler conceptually than macro systems while being hygienic by default
|
||||
|
||||
**Cons:**
|
||||
1. The code of the operative combiner (analogus to a macro invocation) is re-executed at runtime, every time it is encountered
|
||||
2. Additionally, because it is unclear what code will be evaluated as a parameter to a function call and what code must be passed unevaluated to the combiner, little optimization can be done.
|
||||
|
||||
---
|
||||
# Background: Fexprs - detail
|
||||
|
||||
- **Normal Lisp** (Scheme, Common Lisp, etc)
|
||||
- Functions - runtime, evaluate parameters once, return value
|
||||
- Macros - expansion time, do not evaluate parameters, return code to be inlined
|
||||
- Special Forms - look like function or macro calls, but do something special (if, lambda, etc)
|
||||
--
|
||||
|
||||
- **Kraken** (and Kernel)
|
||||
- Combiners
|
||||
- Applicatives (like normal functions, combiners that evaluate all their parameters once in their dynamic environment)
|
||||
- Operatives (combiners that do something unusual with their parameters, do not evaluate them right away)
|
||||
---
|
||||
# Solution: Partial Eval
|
||||
1. Evaluate parts of program that only depend on statically-known data ahead of time and insert resulting values into generated code
|
||||
2. The parts of the resulting partially-evaluated program that only contains static references to a subset of built in combiners and functions (combiners that evaluate their parameters exactly once) can be compiled just like it was a normal Scheme program
|
||||
|
||||
**This is novel! No one has sucessfully pulled this off, to our knowledge.**
|
||||
Why?
|
||||
- Can't use a binding time analysis pass with offline partial evaluation, which eliminates quite a bit of mainline partial evaluation research
|
||||
- Online partial evaluation research generally does not have to deal with the same level of partially/fully dynamic first-class explicit environments
|
||||
---
|
||||
# Research Contributions
|
||||
|
||||
- Programming Language, Kraken, that is entirely based on fexprs
|
||||
- Novel Partial Evaluation algorithm
|
||||
- Heavily specialized to optimize away operative combiners like macros written in a specific way
|
||||
- Compiler
|
||||
- Static calls fully optimized like a normal function call in other languages
|
||||
- Dynamic calls have a single branch of overhead - if normal applicative combiner function like call, post-branch optimized as usual
|
||||
- Optimizes away Y Combinator recursion to static recursive jumps (inc tail call opt)
|
||||
- Prototype faster than Python and other interpreted Lisps
|
||||
- Paper: *Practical compilation of Fexprs using partial evaluation*
|
||||
- Currently under review for ICFP '23
|
||||
---
|
||||
# Kraken
|
||||
|
||||
- Entirly based on fexprs as only means of computation
|
||||
- No macros, no special forms, no seperate functions
|
||||
- Not just tacked-on to an existing language, entirely different foundation
|
||||
- Purely Functional
|
||||
- callbacks/monad-like interaction with outside world
|
||||
- In the Lisp tradition
|
||||
---
|
||||
# Base Language: Syntax
|
||||
|
||||
$$
|
||||
\newcommand{\alt} {\mid}
|
||||
\newcommand{\kraken} {\textit{Kraken}}
|
||||
\newcommand{\kprim} [2] {\langle #1~\textbf{#2} \rangle}
|
||||
\newcommand{\kenv} [3] {\langle \langle #1~|#2,~#3 \rangle \rangle}
|
||||
\newcommand{\kcomb} [5] {\langle \textbf{comb} ~ #1 ~ #2 ~ #3 ~ #4 ~ #5\rangle}
|
||||
\newcommand{\keval} [2] {[\text{eval} ~ #1 ~ #2]}
|
||||
\newcommand{\kcombine} [3] {[\text{combine} ~ #1 ~ #2 ~ #3 ]}
|
||||
$$
|
||||
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{rcll}
|
||||
n & \in & \mathbb{N} & \text{(Integers)} \\\
|
||||
s & \in & Symbols & \\\
|
||||
o & \in & \kprim{1}{eval}, \kprim{0}{vau},\kprim{1}{wrap}, \kprim{1}{unwrap}, & \\\
|
||||
&&\kprim{0}{if0}, \kprim{0}{vif0}, \kprim{1}{int-to-symbol},&\\\
|
||||
&&\kprim{1}{symbol?}, \kprim{1}{int?}, \kprim{1}{combiner?},\kprim{1}{env?},&\\\
|
||||
&&\kprim{1}{array?}, \kprim{1}{len}, \kprim{1}{idx}, \kprim{1}{concat},&\\\
|
||||
&&\kprim{1}{+}, \kprim{1}{<=} &\text{(Primitives)}\\\
|
||||
E &:=& \kenv{(s \leftarrow T)\dots}{}{E} \alt \kenv{(s \leftarrow T)\dots}{s' \leftarrow E}{E} & \text{(Environments)}\\\
|
||||
A &:=& (T \dots)& \text{(Arrays)}\\\
|
||||
C &:=& \kcomb{n}{s'}{E}{(s\dots)}{T} & \text{(Combiners)}\\\
|
||||
S &:=& n \alt o \alt E \alt C & \text{(Self evaluating terms)}\\\
|
||||
V &:=& S \alt s \alt A & \text{(Values)}\\\
|
||||
T &:=& V \alt AT & \text{(Terms)}\\\
|
||||
AT &:=& \keval{T}{E} \alt \kcombine{T}{(T\dots)}{E} & \text{(Active terms)}\\\
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
---
|
||||
# Base Language: Contexts
|
||||
|
||||
$$
|
||||
\newcommand{\Ctxt} {\mathcal{E}}
|
||||
\newcommand{\InCtxt} [1] {\Ctxt[#1]}
|
||||
$$
|
||||
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{rcl}
|
||||
\Ctxt &:=& \square \alt \kcombine{\Ctxt}{(T\dots)}{E} \alt \kcombine{T}{(\Ctxt,T\dots)}{E}\\\
|
||||
&& \alt \kcombine{T}{(T\dots,\Ctxt,T\dots)}{E} \alt \kcombine{T}{(T\dots,\Ctxt)}{E}\\\
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
---
|
||||
# Base: Small-Step Semantics
|
||||
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{rcl}
|
||||
\InCtxt{E} &\rightarrow& \InCtxt{E'} ~ (\text{if } E \rightarrow E')\\\
|
||||
\keval{S}{E} &\rightarrow& S\\\
|
||||
\keval{s}{E} &\rightarrow& lookup(s,E)\\\
|
||||
\keval{(T_1~T_2\dots)}{E} &\rightarrow& \kcombine{\keval{T_1}{E}}{(T_2\dots)}{E}\\\
|
||||
\\\
|
||||
\kcombine{\kcomb{(S~n)}{s'}{E'}{(s\dots)}{Tb}}{(V\dots)}{E} &\rightarrow& \kcombine{\kcomb{n}{s'}{E'}{s}{Tb}}{\\\&&\keval{V}{E}\dots}{E}\\\
|
||||
\kcombine{\kcomb{0}{s'}{E'}{(s\dots)}{Tb}}{(V\dots)}{E} &\rightarrow& \keval{Tb}{\kenv{(s \leftarrow V)\dots}{s' \leftarrow E}{E'}}\\\
|
||||
\\\
|
||||
\kcombine{\kprim{(S~n)}{o}}{(V\dots)}{E} &\rightarrow& \kcombine{\kprim{n}{o}}{(\keval{V}{E}\dots)}{E}\\\
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
---
|
||||
# Base: Selected Primitives
|
||||
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{rcl}
|
||||
\kcombine{\kprim{0}{eval}}{(V~E')}{E} &\rightarrow& \keval{V}{E'}\\\
|
||||
\kcombine{\kprim{0}{vau}}{(s'~(s\dots)~V)}{E} &\rightarrow& \kcomb{0}{s'}{E}{(s\dots)}{V}\\\
|
||||
\kcombine{\kprim{0}{wrap}}{\kcomb{0}{s'}{E'}{(s\dots)}{V}}{E} &\rightarrow& \kcomb{1}{s'}{E'}{(s\dots)}{V}\\\
|
||||
\kcombine{\kprim{1}{unwrap}}{\kcomb{1}{s'}{E'}{(s\dots)}{V}}{E} &\rightarrow& \kcomb{0}{s'}{E'}{(s\dots)}{V}\\\
|
||||
\kcombine{\kprim{0}{if0}}{(V_c~V_t~V_e)}{E} &\rightarrow& \kcombine{\kprim{0}{vif0}}{\\\&&(\keval{V_c}{E}~V_t~V_e)}{E}\\\
|
||||
\kcombine{\kprim{0}{vif0}}{(0~V_t~V_e)}{E} &\rightarrow& \keval{V_t}{E}\\\
|
||||
\kcombine{\kprim{0}{vif0}}{(n~V_t~V_e)}{E} &\rightarrow& \keval{V_e}{E} ~\text{(n != 0)}\\\
|
||||
\kcombine{\kprim{0}{int-to-symbol}}{(n)}{E} &\rightarrow& 'sn ~\text{(symbol made out of the number n)}\\\
|
||||
\kcombine{\kprim{0}{array}}{(V\dots)}{E} &\rightarrow& (V\dots)\\\
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
---
|
||||
# Base Language Summary
|
||||
|
||||
- This base calculus defined above is not only capable of normal lambda-calculus computations with primitives and derived user applicatives, but also supports a superset of macro-like behaviors via its support for operatives.
|
||||
- All of the advantages listed in the introduction apply to this calculus, as do the performance drawbacks, at least if implemented naively. Our partial evaluation and compilation framework will demonstrate how to compile this base language into reasonably performant binaries (WebAssembly bytecode, for our prototype).
|
||||
|
||||
---
|
||||
class: center, middle, title
|
||||
# Slow
|
||||
---
|
||||
# Partial Eval: How it works
|
||||
|
||||
Marco expansion kind of *is* partial evaluation!
|
||||
|
||||
- Online, no binding time analysis
|
||||
- Partially Evaluate combiners with partially-static environments
|
||||
- Prevent infinate recursion by blocking on
|
||||
- Recursive calls underneath a partially evaluated body
|
||||
- Recursive path to *if*
|
||||
- Track call frames that need to be real to progress on every AST node
|
||||
- Can zero-in on areas that will make progress
|
||||
- Also tracks nodes previously stopped by recursion-stopper in case no longer under the frame that stopped the recursion
|
||||
- Evaluate derived calls with parameter values, inline result even if not value if it doesn't depend on call frame
|
||||
---
|
||||
# Partial Eval Rule Walkthrough
|
||||
|
||||
---
|
||||
class: center, middle, title
|
||||
# Optimizations
|
||||
---
|
||||
# Optimization Adgenda
|
||||
|
||||
- "The Trick" - handling dynamic calls
|
||||
- Lazy Environment Instantiation
|
||||
- Type-Inference-Based Primitive Inlining
|
||||
- Immediately-Called Closure Inlining
|
||||
- Y-Combinator Elimination
|
||||
---
|
||||
# "The Trick"
|
||||
|
||||
<pre><code class="remark_code">(lambda (f) (f (+ 1 2)))
|
||||
</code></pre>
|
||||
To something like
|
||||
<pre><code class="remark_code">function(f):
|
||||
if wrap_level(f) == 1:
|
||||
f(3)
|
||||
else:
|
||||
f([`+ 1 2])
|
||||
</code></pre>
|
||||
|
||||
- Insert runtime check for dynamic call sites
|
||||
- When compiling in the wraplevel=1 side of conditional, further partial evaluate the parameter value
|
||||
- Only a single branch of overhead for dynamic function calls
|
||||
|
||||
*Really a critical part of the dance, not an optional optimization*
|
||||
|
||||
---
|
||||
# Lazy Environment Instantiation
|
||||
|
||||
<pre><code class="remark_code">(lambda (f) (f))
|
||||
</code></pre>
|
||||
compiled to equivalent of
|
||||
<pre><code class="remark_code">function(f):
|
||||
if uses_env(f):
|
||||
if not env_cache:
|
||||
env_cache = make_env()
|
||||
f(env_cache)
|
||||
else:
|
||||
f()
|
||||
</code></pre>
|
||||
---
|
||||
# Type-Inference-Based Primitive Inlining
|
||||
|
||||
For instance, consider the following code:
|
||||
<pre><code class="remark_code">(if (and (array? a) (= 3 (len a))) (idx a 2)
|
||||
nil)
|
||||
</code></pre>
|
||||
|
||||
- Call to *idx* fully inlined without type or bounds checking
|
||||
- No type information is needed to inline type predicates, as they only need to look at the tag bits.
|
||||
- Equality checks can be inlined as a simple word/ptr compare if any of its parameters are of a type that can be word/ptr compared (ints, bools, and symbols).
|
||||
|
||||
<pre><code class="remark_code">if is_array(a) and len(a) == 3:
|
||||
*(a+2)
|
||||
else: nil
|
||||
</code></pre>
|
||||
|
||||
---
|
||||
# Immediately-Called Closure Inlining
|
||||
|
||||
Inlining calls to closure values that are allocated and then immediately used:
|
||||
|
||||
This is partial-evaled
|
||||
<pre><code class="remark_code">(let (b (+ a 2))
|
||||
(+ b 3))
|
||||
</code></pre>
|
||||
to this
|
||||
<pre><code class="remark_code">((wrap (vau (b) (+ b 3))) (+ a 2))
|
||||
</code></pre>
|
||||
and then inlined (plus lazy environment allocation)
|
||||
<pre><code class="remark_code">b = a + 2;
|
||||
b + 3
|
||||
</code></pre>
|
||||
|
||||
|
||||
---
|
||||
# Y-Combinator Elimination
|
||||
<pre><code class="remark_code">(Y (lambda (self) (lambda (n)
|
||||
(if (= 0 n) 1
|
||||
(* n (self (- n 1)))))))
|
||||
</code></pre>
|
||||
|
||||
- When compiling a combiner, pre-emptive memoization
|
||||
- Partial-evaluation to normalize
|
||||
- Eager lang - extra lambda - eta-conversion in the compiler
|
||||
|
||||
<pre><code class="remark_code">def fact(n):
|
||||
if n == 0:
|
||||
1
|
||||
else:
|
||||
n * fact(n - 1)
|
||||
</code></pre>
|
||||
|
||||
---
|
||||
# Outcomes
|
||||
1. All macro-like combiner calls are partially evaluated away
|
||||
- No downside to using fexprs for everything
|
||||
2. No interpreted evaluation calls remain
|
||||
3. Optimizations allow reasonable performance
|
||||
---
|
||||
# Benchmarks
|
||||
|
||||
- Fib - Calculating the nth Fibonacci number
|
||||
- RB-Tree - Inserting n items into a red-black tree, then traversing the tree to sum its values
|
||||
- Deriv - Computing a symbolic derivative of a large expression
|
||||
- Cfold - Constant-folding a large expression
|
||||
- NQueens - Placing n number of queens on the board such that no two queens are diagonal, vertical, or horizontal from each other
|
||||
|
||||
There isn't a standard suite to use here, this was a set we liked from a previosu paper that is relevent for both functional and imperitive languages.
|
||||
|
||||
---
|
||||
# Results:
|
||||
|
||||
Number of eval calls with no partial evaluation for Fexprs
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{||c | c c c c c ||}
|
||||
\hline
|
||||
&Evals & Eval w1 Calls & Eval w0 Calls & Comp Dyn & Comp Dyn\\\
|
||||
& & & & w1 Calls & w0 Calls\\\
|
||||
\hline\hline
|
||||
Cfold 5 & 10897376 & 2784275 & 879066 & 1 & 0 \\\
|
||||
\hline
|
||||
Deriv 2 & 11708558 & 2990090 & 946500 & 1 & 0 \\\
|
||||
\hline
|
||||
NQueens 7 & 13530241 & 3429161 & 1108393 & 1 & 0 \\\
|
||||
\hline
|
||||
Fib 30 & 119107888 & 30450112 & 10770217 & 1 & 0 \\\
|
||||
\hline
|
||||
RB-Tree 10 & 5032297 & 1291489 & 398104 & 1 & 0 \\\
|
||||
\hline
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
Number of eval calls in Partially Evaluated Fexprs
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{||c | c c c c c ||}
|
||||
\hline
|
||||
&Evals & Eval w1 Calls & Eval w0 Calls & Comp Dyn & Comp Dyn\\\
|
||||
& & & & w1 Calls & w0 Calls\\\
|
||||
\hline\hline
|
||||
Cfold 5 & 0 & 0 & 0 & 0 & 0 \\\
|
||||
\hline
|
||||
Deriv 2 & 0 & 0 & 0 & 2 & 0 \\\
|
||||
\hline
|
||||
NQueens 7 & 0 & 0 & 0 & 0 & 0 \\\
|
||||
\hline
|
||||
Fib 30 & 0 & 0 & 0 & 0 & 0 \\\
|
||||
\hline
|
||||
RB-Tree 10 & 0 & 0 & 0 & 10 & 0 \\\
|
||||
\hline
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
---
|
||||
# Results:
|
||||
Number of calls to the runtime's eval function for RB-Tree. The table shows the non-partial evaluation numbers -> partial evaluation numbers.
|
||||
|
||||
.mathSize8[
|
||||
$$
|
||||
\begin{array}{||c | c c c c c ||}
|
||||
\hline
|
||||
&Evals & Eval w1 Calls & Eval w0 Calls & Comp Dyn & Comp Dyn\\\
|
||||
& & & & w1 Calls & w0 Calls\\\
|
||||
\hline\hline
|
||||
RB-Tree 7 & 2952848 -> 0 & 757932 -> 0 & 233513 -> 0 & 1 -> 7 & 0 -> 0\\\
|
||||
\hline
|
||||
RB-Tree 8 & 3532131 -> 0 & 906548 -> 0 & 279379 -> 0 & 1 -> 8 & 0 -> 0\\\
|
||||
\hline
|
||||
RB-Tree 9 & 4278001 -> 0 & 1097965 -> 0 & 3383831 -> 0 & 1 -> 9 & 0 -> 0\\\
|
||||
\hline
|
||||
\end{array}
|
||||
$$
|
||||
]
|
||||
|
||||
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results: (log scale)
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Results:
|
||||
.fullWidthImg[]
|
||||
---
|
||||
# Research Conclusion
|
||||
|
||||
- Purely functional Lisp based entirely on Fexprs - Kraken
|
||||
- Novel Partial Evaluation algorithm specifically designed to remove all macro-like fexprs
|
||||
- No interpreted evaluation calls remain
|
||||
- Compiler implementing partial evaluation and additional optimizations achiving feasible performance (70,000x+ speedup, etc)
|
||||
|
||||
*Little to no downside to basing Lisp-like functional language on fexprs*
|
||||
---
|
||||
# Current & Future
|
||||
|
||||
- Partial Evaluation / Kraken evolution:
|
||||
- More normal language: purely functional Scheme
|
||||
- More standard Scheme
|
||||
- Environments as association-lists
|
||||
- Fully manipulateable as normal list/pairs
|
||||
- Partial evaluation that supports naturally-written operative combiners, like the running *or* example
|
||||
- Performance: Better Reference Counting, Tail-Recursion Modulo Cons
|
||||
- Implement Delimited Continuations as Fexprs
|
||||
- Implement Automatic Differentiation as Fexprs
|
||||
- Allow type systems to be built using Fexprs, like the type-systems-as-macros paper
|
||||
- Investigate Hardware as Fexprs
|
||||
---
|
||||
class: center, middle, title
|
||||
# Thank you!
|
||||
---
|
||||
class: center, middle, title
|
||||
# Backup Slides
|
||||
---
|
||||
# Partial Eval Semantics:
|
||||
|
||||
.pull-left[]
|
||||
|
||||
.pull-right[]
|
||||
|
||||
---
|
||||
# Partial Eval Semantics:
|
||||
|
||||
.pull-left[]
|
||||
|
||||
.pull-right[]
|
||||
|
||||
---
|
||||
# Partial Eval Semantics:
|
||||
|
||||
.pull-left[]
|
||||
|
||||
.pull-right[]
|
||||
|
||||
---
|
||||
# Background: Fexprs - detail
|
||||
<pre><code class="remark_code"> foldr:
|
||||
(rec-lambda recurse (f z l)
|
||||
(if (= nil l)
|
||||
z
|
||||
(lapply f (list (car l) (recurse f z (cdr l))))))
|
||||
</code></pre>
|
||||
(lapply reduces the wrap-level of the function by 1, equivalent to quoting the inputs)
|
||||
<pre><code class="remark_code"> foldr:
|
||||
(rec-lambda recurse (f z l)
|
||||
(if (= nil l)
|
||||
z
|
||||
(f (car l) (recurse f z (cdr l)))))
|
||||
</code></pre>
|
||||
---
|
||||
# Background: Fexprs - detail
|
||||
|
||||
All special forms in Kaken are combiners too, and are thus also first class.
|
||||
In this case, we can not only pass the raw _if_ around, but we can make an _inverse_if_ which inverts its condition (kinda macro-like) and pass it around.
|
||||
<pre><code class="remark_code">> (let ((use_if (lambda (new_if) (new_if true 1 2)))
|
||||
(inverse_if (vau de (c t e) (if (not (eval c de))
|
||||
(eval t de)
|
||||
(eval e de))))
|
||||
)
|
||||
(list (use_if if) (use_if inverse_if)))
|
||||
(1 2)
|
||||
</code></pre>
|
||||
What were special forms in Lisp are now just built-in combiners in Kraken.
|
||||
*if* is not any more special than *+*, and in both cases you can define your own versions that would be indistinguishable, and in both cases they are first-class.
|
||||
---
|
||||
# Solution: Partial Eval
|
||||
1. Partially evaluate a purely functional version of this language in a nearly-single pass over the entire program
|
||||
2. Environment chains consisting of both "real" environments with every contained symbol mapped to a value and "fake" environments that only have placeholder values.
|
||||
4. The parts of the resulting partially-evaluated program that only contains static references to a subset of built in combiners and functions (combiners that evaluate their parameters exactly once) can be compiled just like it was a normal Scheme program
|
||||
---
|
||||
# Intuition
|
||||
|
||||
Macros, especially *define-macro* macros, are essentially functions that run at expansion time and compute new code from old code.
|
||||
This is essentially partial evaluation / inlining, depending on how you look at it.
|
||||
|
||||
It thus makes sense to ask if we can identify and partial evaluate / inline operative combiners to remove and optimize them like macros. Indeed, if we can determine what calls are to applicative combiners we can optimize their parameters, and if we can determine what calls are to macro-like operative combiners, we can try to do the equivalent of macro expansion.
|
||||
|
||||
For Kraken, this is exactly what we do, using a specialized form of Partial Evaluation to do so.
|
||||
---
|
||||
# Selected Explanations
|
||||
|
||||
.mathSize9[
|
||||
- \\(\kprim{0}{eval}\\): evaluates its argument in the given environment.
|
||||
- \\(\kprim{0}{vau}\\): creates a new combiner and is analogous to lambda in other languages, but with a "wrap level" of 0, meaning the created combiner does not evaluate its arguments.
|
||||
- \\(\kprim{0}{wrap}\\): increments the wrap level of its argument. Specifically, we are "wrapping" a "wrap level" n combiner (possibly "wrap level" 0, created by *vau* to create a "wrap level" n+1 combiner. A wrap level 1 combiner is analogous to regular functions in other languages.
|
||||
- \\(\kprim{0}{unwrap}\\): decrements the "wrap level" of the passed combiner, the inverse of *wrap*.
|
||||
- \\(\kprim{0}{if}\\): evaluates only its condition and converts to the \\(\kprim{0}{vif}\\) primitive for the next step. It cannot evaluate both branches due to the risk of non-termination.
|
||||
- \\(\kprim{0}{vif}\\): evaluates and returns one of the two branches based on if the condition is non-zero.
|
||||
- \\(\kprim{0}{int-to-symbol}\\): creates a symbol out of an integer.
|
||||
- \\(\kprim{0}{array}\\): returns an array made out of its parameter list.
|
||||
]
|
||||
|
||||
---
|
||||
# Less Interesting Prims
|
||||
|
||||
.mathSize9[
|
||||
- \\(\kcombine{\kprim{0}{type-test?}}{(A)}{E}\\): *array?*, *comb?*, *int?*, and *symbol?*, each return 0 if the single argument is of that type, otherwise they return 1.
|
||||
- \\(\kcombine{\kprim{0}{len}}{(A)}{E}\\): returns the length of the single array argument.
|
||||
- \\(\kcombine{\kprim{0}{idx}}{(A~n)}{E}\\): returns the nth item array A.
|
||||
- \\(\kcombine{\kprim{0}{concat}}{(A~B)}{E}\\): combines both array arguments into a single concatenated array.
|
||||
- \\(\kcombine{\kprim{0}{+}}{(A~A)}{E}\\): adds its arguments
|
||||
- \\(\kcombine{\kprim{0}{<=}}{(A~A)}{E}\\): returns 0 if its arguments are in increasing order, and 1 otherwise.
|
||||
]
|
||||
---
|
||||
# Results:
|
||||
.pull-left[]
|
||||
|
||||
.pull-right[]
|
||||
|
||||
---
|
||||
# Introduction
|
||||
|
||||
Here's some test code:
|
||||
|
||||
.run_container[
|
||||
<div class="editor" id="hello_editor">; Of course
|
||||
(println "Hello World")
|
||||
; Just print 3
|
||||
(println "Math workssss:" (+ 1 2 4))
|
||||
</div>
|
||||
]
|
||||
--
|
||||
.rerun_container[
|
||||
<pre><code class="remark_code" id="hello_editor_output">output here...</code></pre>
|
||||
<button class="run_button" onclick="executeKraken(hello_editor_jar[1].toString(), 'hello_editor_output')">Rerun</button> <br>
|
||||
]
|
||||
|
||||
</textarea>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="./default.min.css">
|
||||
<script src="./highlight.min.js"></script>
|
||||
<script type="module">
|
||||
import {CodeJar} from './codejar.js'
|
||||
window.loadEverything = function() {
|
||||
var renderMath = function() {
|
||||
//renderMathInElement(document.body);
|
||||
//renderMathInElement(document.body, {delimiters: [
|
||||
// {left: "$$", right: "$$", display: true},
|
||||
// {left: "$", right: "$", display: false},
|
||||
// {left: "\\[", right: "\\]", display: true},
|
||||
// {left: "\\(", right: "\\)", display: false},
|
||||
//]});
|
||||
}
|
||||
//var slideshow = remark.create({}, renderMath);
|
||||
var slideshow = remark.create();
|
||||
document.querySelectorAll('.editor').forEach((editor_div) => {
|
||||
if (window[editor_div.id + "_jar"] == undefined) {
|
||||
window[editor_div.id + "_jar"] = []
|
||||
}
|
||||
window[editor_div.id + "_jar"].push(CodeJar(editor_div, hljs.highlightElement))
|
||||
});
|
||||
slideshow.on('showSlide', function (slide) {
|
||||
//console.log('Navigated to', slide)
|
||||
for (const c of slide.content) {
|
||||
if (c.class == "run_container") {
|
||||
//console.log("found editor", c)
|
||||
const re = /class="editor" id="([^"]+)"/;
|
||||
let id = c.content[0].match(re)[1]
|
||||
let editors = window[id + "_jar"]
|
||||
if (slide.properties.continued == "true") {
|
||||
editors[1].updateCode(editors[0].toString())
|
||||
//console.log("Got editors", editors, "running kraken")
|
||||
executeKraken(editors[1].toString(), id + "_output")
|
||||
} else {
|
||||
editors[0].updateCode(editors[1].toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {
|
||||
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
|
||||
}
|
||||
});
|
||||
MathJax.Hub.Configured();
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
var output_name = ""
|
||||
var Module = {
|
||||
noInitialRun: true,
|
||||
onRuntimeInitialized: () => {
|
||||
},
|
||||
print: txt => {
|
||||
document.getElementById(output_name).innerHTML += txt + "\n";
|
||||
},
|
||||
printErr: txt => {
|
||||
document.getElementById(output_name).innerHTML += "STDERR:[" + txt + "]\n";
|
||||
}
|
||||
};
|
||||
function executeKraken(code, new_output_name) {
|
||||
output_name = new_output_name
|
||||
document.getElementById(new_output_name).innerHTML = "";
|
||||
Module.callMain(["-C", code]);
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="k_prime.js"></script>
|
||||
<script src="remark-latest.min.js"></script>
|
||||
<!--<script src="MathJax.js"></script>-->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML&delayStartupUntil=configured" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
84
website/recursive.css
Normal file
@@ -0,0 +1,84 @@
|
||||
@font-face {
|
||||
font-family: 'Recursive';
|
||||
font-style: oblique 0deg 15deg;
|
||||
font-weight: 300 1000;
|
||||
font-display: swap;
|
||||
src: url(./Recursive.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
:root {
|
||||
--rec-wght: 400;
|
||||
--rec-slnt: 0;
|
||||
--rec-mono: 0;
|
||||
--rec-casl: 0;
|
||||
--rec-csrv: 0;
|
||||
}
|
||||
* {
|
||||
font-variation-settings: "wght" var(--rec-wght),
|
||||
"slnt" var(--rec-slnt),
|
||||
"MONO" var(--rec-mono),
|
||||
"CASL" var(--rec-casl),
|
||||
"CRSV" var(--rec-csrv);
|
||||
}
|
||||
body {
|
||||
max-width: 45em;
|
||||
margin: 1em auto;
|
||||
padding: 0 .62em;
|
||||
font: 1.2em/1.62 'Recursive', sans-serif;
|
||||
}
|
||||
//body, .remark-slide-content { background-color: #eff3f5; }
|
||||
body, .remark-slide-content { background-color: #f5f3ef; }
|
||||
h1, h2, h3, h4 {
|
||||
line-height:0.4;
|
||||
--rec-wght: 900;
|
||||
--rec-slnt: -10;
|
||||
--rec-casl: 0.5;
|
||||
--rec-crsv: 1;
|
||||
--rec-mono: 0;
|
||||
letter-spacing: -0.015em;
|
||||
font-size: 4em;
|
||||
}
|
||||
h1 {
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 0.4rem;
|
||||
}
|
||||
h2 { font-size: 3em; }
|
||||
h3 { font-size: 1.5em; }
|
||||
h4 { font-size: 1.2em; }
|
||||
i { --rec-slnt: -14; }
|
||||
em { --rec-slnt: -14; }
|
||||
b { --rec-wght: 600; }
|
||||
strong { --rec-wght: 600; }
|
||||
.run_container { position: relative; }
|
||||
.editor, .remark-code, .remark-inline-code {
|
||||
font-family: 'Recursive', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||
//height: 7em;
|
||||
letter-spacing: normal;
|
||||
tab-size: 4;
|
||||
}
|
||||
.output {
|
||||
margin-block-start: 1rem;
|
||||
font-family: 'Recursive', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
tab-size: 4;
|
||||
height: 5em;
|
||||
width: 100%;
|
||||
}
|
||||
.run_button {
|
||||
font-family: 'Recursive', sans-serif;
|
||||
font-size: 1em;
|
||||
--rec-wght: 900;
|
||||
--rec-slnt: -10;
|
||||
--rec-casl: 0.5;
|
||||
--rec-crsv: 1;
|
||||
--rec-mono: 0;
|
||||
letter-spacing: -0.015em;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
18
website/remark-latest.min.js
vendored
Normal file
77
website/slick.css
Normal file
@@ -0,0 +1,77 @@
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
font-style: oblique 0deg 10deg;
|
||||
src: url("./Inter.var.woff2?v=3.19") format("woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url("./JetBrainsMono-Regular.woff2") format("woff2");
|
||||
}
|
||||
:root {
|
||||
--rec-wght: 400;
|
||||
--rec-slnt: 0;
|
||||
}
|
||||
* {
|
||||
font-variation-settings: "wght" var(--rec-wght),
|
||||
"slnt" var(--rec-slnt);
|
||||
}
|
||||
body {
|
||||
max-width: 45em;
|
||||
margin: 1em auto;
|
||||
padding: 0 .62em;
|
||||
font: 1.2em/1.62 'Inter', sans-serif;
|
||||
}
|
||||
h1, h2, h3, h4 {
|
||||
line-height:1.0;
|
||||
--rec-wght: 700;
|
||||
}
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
--rec-wght: 900;
|
||||
letter-spacing: -0.025em;
|
||||
//--rec-slnt: -15;
|
||||
line-height:0.2;
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 0.4rem;
|
||||
//border-bottom: 0.08em solid;
|
||||
//border-left: 0.1em solid;
|
||||
//display: inline-block;
|
||||
}
|
||||
h2 { font-size: 3em; }
|
||||
h3 { font-size: 1.5em; }
|
||||
h4 { font-size: 1.2em; }
|
||||
i { --rec-slnt: -14; }
|
||||
b { --rec-wght: 600; }
|
||||
.run_container { position: relative; }
|
||||
.editor {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||
height: 7em;
|
||||
letter-spacing: normal;
|
||||
tab-size: 4;
|
||||
}
|
||||
.output {
|
||||
margin-block-start: 1rem;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 1rem;
|
||||
--rec-mono: 1;
|
||||
tab-size: 4;
|
||||
height: 5em;
|
||||
width: 100%;
|
||||
}
|
||||
.run_button {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 1em;
|
||||
--rec-wght: 900;
|
||||
--rec-slnt: -15;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
5
website/slides_to_add
Normal file
@@ -0,0 +1,5 @@
|
||||
x lisp tree
|
||||
x explain quote
|
||||
x show fold's internals
|
||||
x fix if0 primitive
|
||||
_ partial evaluation
|
||||