Compare commits
51 Commits
partially_
...
56c6b3f5f7
| Author | SHA1 | Date | |
|---|---|---|---|
| 56c6b3f5f7 | |||
| 82c38a32cf | |||
| 2787b95837 | |||
| 656cfe95ae | |||
| 75d025bcb2 | |||
| 41aa05dc97 | |||
| 774eb668de | |||
| c1a0608b7c | |||
| 15cab8799d | |||
| 6edbe7d2c8 | |||
| b077daf12e | |||
| f4ae4db92d | |||
| b03122c7b8 | |||
| d6cf6a6b64 | |||
| 3b858eda98 | |||
| 8b9a0a0f2d | |||
| ce5ab1dd99 | |||
| 4126e25463 | |||
| d44480bf6c | |||
| 093f3c0453 | |||
| f82101e63f | |||
| ea1516fbd1 | |||
| 82bfb5bc7b | |||
| 7431dbe4b7 | |||
| 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 |
2
.gitignore
vendored
@@ -9,8 +9,8 @@ build-ninja
|
||||
*.swi
|
||||
*.swj
|
||||
*.swk
|
||||
*.png
|
||||
.*.un~
|
||||
callgrind*
|
||||
.stfolder
|
||||
*.wasm
|
||||
*/target
|
||||
|
||||
12
README.md
@@ -5,11 +5,19 @@ The Kraken Programming Language
|
||||
|
||||
(more information online at http://kraken-lang.org/ which is also under construction / needs to be updated / has a try-it-online feature for an older version without partial evaluation)
|
||||
|
||||
Currently developing the third iteration, a Scheme-like based on a functional Vau calculus partially-evaluated for efficency and compiling to WebAssembly.
|
||||
|
||||
*Heavily* inspiried by John Shutt's thesis: https://web.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf
|
||||
with partial evaluation during compilation to make it efficient.
|
||||
|
||||
Currently developing the fourth iteration, a Scheme-like based on a functional Vau calculus JIT compiled for speed.
|
||||
|
||||
Working up to a JIT for fexprs by starting with
|
||||
|
||||
- sl - a Simple Lisp JIT (WIP)
|
||||
- ?
|
||||
- ?
|
||||
- ?
|
||||
- kv - A fexpr interpeter with mutation and delimited continuations - need to add a JIT to this
|
||||
|
||||
|
||||
koka_bench: Licensed under Apache-2.0, as they are derived from the benchmarks of the Koka project, see the readme and license in koka_bench for more, or https://github.com/koka-lang/koka for the source project.
|
||||
|
||||
|
||||
88
basic_dyns
@@ -1,88 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RB-TREE
|
||||
|
||||
evals all_evals evaled_wrap_1 evaled_wrap_0 compiled_dyn_1 compiled_dyn_0
|
||||
non-PE10 114_170 5_032_297 1_291_489 398_104 1 0
|
||||
PE10 0 0 0 0 10 0
|
||||
nonPE9 97087 4278001 1097965 338383 1 0
|
||||
PE9 0 0 0 0 9 0
|
||||
nonPE8 80160 3532131 906548 279379 1 0
|
||||
PE8 0 0 0 0 8 0
|
||||
nonPE7 67050 2952848 757932 233513 1 0
|
||||
PE7 0 0 0 0 7 0
|
||||
nonPE6 50361 2219792 569723 175593 1 0
|
||||
PE6 0 0 0 0 6 0
|
||||
nonPE5 37299 1643049 421745 129938 1 0
|
||||
PE5 0 0 0 0 5 0
|
||||
nonPE4 24393 1074730 275873 85000 1 0
|
||||
PE4 0 0 0 0 4 0
|
||||
nonPE3 15304 672998 172802 53200 1 0
|
||||
PE3 0 0 0 0 3 0
|
||||
nonPE2 6453 284080 72939 22484 1 0
|
||||
PE2 0 0 0 0 2 0
|
||||
nonPE1 1385 59899 15413 4750 1 0
|
||||
PE1 0 0 0 0 1 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Fib
|
||||
|
||||
evals all_evals evaled_wrap_1 evaled_wrap_0 compiled_dyn_1 compiled_dyn_0
|
||||
non-PE35 29860726 1320920726 337695363 119442881 1 0
|
||||
non-PE30 2692560 119107888 30450112 10770217 1 0
|
||||
non-PE25 242808 10740492 2745825 971209 1 0
|
||||
non-PE20 21914 969010 247731 87633 1 0
|
||||
non-PE15 1996 87916 22478 7961 1 0
|
||||
non-PE10 200 8468 2167 777 1 0
|
||||
|
||||
PE10 0 0 0 0 0 0
|
||||
PE15 0 0 0 0 0 0
|
||||
PE20 0 0 0 0 0 0
|
||||
PE25 0 0 0 0 0 0
|
||||
PE30 0 0 0 0 0 0
|
||||
PE35 0 0 0 0 0 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cfold
|
||||
evals all_evals evaled_wrap_1 evaled_wrap_0 compiled_dyn_1 compiled_dyn_0
|
||||
non-PE5 239660 10897376 2784275 879066 1 0
|
||||
PE5 0 0 0 0 0 0
|
||||
|
||||
|
||||
deriv
|
||||
evals all_evals evaled_wrap_1 evaled_wrap_0 compiled_dyn_1 compiled_dyn_0
|
||||
non-PE2 257693 11708558 2990090 946500 1 0
|
||||
PE2 0 0 0 0 2 0
|
||||
|
||||
|
||||
nqueens
|
||||
evals all_evals evaled_wrap_1 evaled_wrap_0 compiled_dyn_1 compiled_dyn_0
|
||||
non-PE7 271720 13530241 3429161 1108393 1 0
|
||||
PE7 0 0 0 0 0 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
scheme --script ../../partial_eval.scm rbtree-opt.kp no_partial_eval && mv csc_out.wasm rbtree-opt.wasm && time wasmtime ./rbtree-opt.wasm 10
|
||||
scheme --script ../../partial_eval.scm rbtree-opt.kp && mv csc_out.wasm rbtree-opt.wasm && time wasmtime ./rbtree-opt.wasm 10
|
||||
|
||||
|
||||
12
doc/.gitignore
vendored
@@ -1,12 +0,0 @@
|
||||
*.swp
|
||||
*.zip
|
||||
*.aux
|
||||
*.bbl
|
||||
*.blg
|
||||
*.log
|
||||
*.out
|
||||
*.pdf
|
||||
*.nav
|
||||
*.snm
|
||||
*.toc
|
||||
*.vrb
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
@phdthesis{shutt2010fexprs,
|
||||
title={Fexprs as the basis of Lisp function application or \$vau: the ultimate abstraction},
|
||||
author={Shutt, John N},
|
||||
year={2010}
|
||||
}
|
||||
@article{kearsleyimplementing,
|
||||
title={Implementing a Vau-based Language With Multiple Evaluation Strategies},
|
||||
author={Kearsley, Logan}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
rm presentation.aux
|
||||
rm presentation.bbl
|
||||
rm presentation.blg
|
||||
rm presentation.log
|
||||
rm presentation.out
|
||||
rm presentation.pdf
|
||||
#pdflatex presentation && bibtex presentation && pdflatex presentation && bibtex presentation && pdflatex presentation && bibtex presentation && evince presentation.pdf
|
||||
pdflatex presentation && evince presentation.pdf
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
rm writeup.aux
|
||||
rm writeup.bbl
|
||||
rm writeup.blg
|
||||
rm writeup.log
|
||||
rm writeup.out
|
||||
rm writeup.pdf
|
||||
pdflatex writeup && bibtex writeup && pdflatex writeup && bibtex writeup && pdflatex writeup && bibtex writeup && evince writeup.pdf
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"niv": {
|
||||
"branch": "master",
|
||||
"description": "Easy dependency management for Nix projects",
|
||||
"homepage": "https://github.com/nmattia/niv",
|
||||
"owner": "nmattia",
|
||||
"repo": "niv",
|
||||
"rev": "65a61b147f307d24bfd0a5cd56ce7d7b7cc61d2e",
|
||||
"sha256": "17mirpsx5wyw262fpsd6n6m47jcgw8k2bwcp1iwdnrlzy4dhcgqh",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/nmattia/niv/archive/65a61b147f307d24bfd0a5cd56ce7d7b7cc61d2e.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
},
|
||||
"nixpkgs": {
|
||||
"branch": "master",
|
||||
"description": "Nix Packages collection",
|
||||
"homepage": "",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2b65a74aba274a06a673dfb6f28b96cbe0b032fb",
|
||||
"sha256": "0f62z6q00dpxnf4c5ip8362kzzcmnlhx6fbia6dr97a21fzbc8aq",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/2b65a74aba274a06a673dfb6f28b96cbe0b032fb.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
},
|
||||
"nixpkgs-mozilla": {
|
||||
"branch": "master",
|
||||
"description": "mozilla related nixpkgs (extends nixos/nixpkgs repo)",
|
||||
"homepage": "",
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"rev": "0510159186dd2ef46e5464484fbdf119393afa58",
|
||||
"sha256": "1c6r5ldkh71v6acsfhni7f9sxvi7xrqzshcwd8w0hl2rrqyzi58w",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/mozilla/nixpkgs-mozilla/archive/0510159186dd2ef46e5464484fbdf119393afa58.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
# This file has been generated by Niv.
|
||||
|
||||
let
|
||||
|
||||
#
|
||||
# The fetchers. fetch_<type> fetches specs of type <type>.
|
||||
#
|
||||
|
||||
fetch_file = pkgs: name: spec:
|
||||
let
|
||||
name' = sanitizeName name + "-src";
|
||||
in
|
||||
if spec.builtin or true then
|
||||
builtins_fetchurl { inherit (spec) url sha256; name = name'; }
|
||||
else
|
||||
pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
|
||||
|
||||
fetch_tarball = pkgs: name: spec:
|
||||
let
|
||||
name' = sanitizeName name + "-src";
|
||||
in
|
||||
if spec.builtin or true then
|
||||
builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
|
||||
else
|
||||
pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
|
||||
|
||||
fetch_git = name: spec:
|
||||
let
|
||||
ref =
|
||||
if spec ? ref then spec.ref else
|
||||
if spec ? branch then "refs/heads/${spec.branch}" else
|
||||
if spec ? tag then "refs/tags/${spec.tag}" else
|
||||
abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
|
||||
in
|
||||
builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
|
||||
|
||||
fetch_local = spec: spec.path;
|
||||
|
||||
fetch_builtin-tarball = name: throw
|
||||
''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=tarball -a builtin=true'';
|
||||
|
||||
fetch_builtin-url = name: throw
|
||||
''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
|
||||
$ niv modify ${name} -a type=file -a builtin=true'';
|
||||
|
||||
#
|
||||
# Various helpers
|
||||
#
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
|
||||
sanitizeName = name:
|
||||
(
|
||||
concatMapStrings (s: if builtins.isList s then "-" else s)
|
||||
(
|
||||
builtins.split "[^[:alnum:]+._?=-]+"
|
||||
((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
|
||||
)
|
||||
);
|
||||
|
||||
# The set of packages used when specs are fetched using non-builtins.
|
||||
mkPkgs = sources: system:
|
||||
let
|
||||
sourcesNixpkgs =
|
||||
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
|
||||
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
|
||||
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
|
||||
in
|
||||
if builtins.hasAttr "nixpkgs" sources
|
||||
then sourcesNixpkgs
|
||||
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
|
||||
import <nixpkgs> {}
|
||||
else
|
||||
abort
|
||||
''
|
||||
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
|
||||
add a package called "nixpkgs" to your sources.json.
|
||||
'';
|
||||
|
||||
# The actual fetching function.
|
||||
fetch = pkgs: name: spec:
|
||||
|
||||
if ! builtins.hasAttr "type" spec then
|
||||
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
|
||||
else if spec.type == "file" then fetch_file pkgs name spec
|
||||
else if spec.type == "tarball" then fetch_tarball pkgs name spec
|
||||
else if spec.type == "git" then fetch_git name spec
|
||||
else if spec.type == "local" then fetch_local spec
|
||||
else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
|
||||
else if spec.type == "builtin-url" then fetch_builtin-url name
|
||||
else
|
||||
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
|
||||
|
||||
# If the environment variable NIV_OVERRIDE_${name} is set, then use
|
||||
# the path directly as opposed to the fetched source.
|
||||
replace = name: drv:
|
||||
let
|
||||
saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
|
||||
ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
|
||||
in
|
||||
if ersatz == "" then drv else
|
||||
# this turns the string into an actual Nix path (for both absolute and
|
||||
# relative paths)
|
||||
if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
|
||||
|
||||
# Ports of functions for older nix versions
|
||||
|
||||
# a Nix version of mapAttrs if the built-in doesn't exist
|
||||
mapAttrs = builtins.mapAttrs or (
|
||||
f: set: with builtins;
|
||||
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
|
||||
);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
|
||||
range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
|
||||
stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
|
||||
stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
|
||||
concatMapStrings = f: list: concatStrings (map f list);
|
||||
concatStrings = builtins.concatStringsSep "";
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
|
||||
optionalAttrs = cond: as: if cond then as else {};
|
||||
|
||||
# fetchTarball version that is compatible between all the versions of Nix
|
||||
builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
|
||||
let
|
||||
inherit (builtins) lessThan nixVersion fetchTarball;
|
||||
in
|
||||
if lessThan nixVersion "1.12" then
|
||||
fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||
else
|
||||
fetchTarball attrs;
|
||||
|
||||
# fetchurl version that is compatible between all the versions of Nix
|
||||
builtins_fetchurl = { url, name ? null, sha256 }@attrs:
|
||||
let
|
||||
inherit (builtins) lessThan nixVersion fetchurl;
|
||||
in
|
||||
if lessThan nixVersion "1.12" then
|
||||
fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
|
||||
else
|
||||
fetchurl attrs;
|
||||
|
||||
# Create the final "sources" from the config
|
||||
mkSources = config:
|
||||
mapAttrs (
|
||||
name: spec:
|
||||
if builtins.hasAttr "outPath" spec
|
||||
then abort
|
||||
"The values in sources.json should not have an 'outPath' attribute"
|
||||
else
|
||||
spec // { outPath = replace name (fetch config.pkgs name spec); }
|
||||
) config.sources;
|
||||
|
||||
# The "config" used by the fetchers
|
||||
mkConfig =
|
||||
{ sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
|
||||
, sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
|
||||
, system ? builtins.currentSystem
|
||||
, pkgs ? mkPkgs sources system
|
||||
}: rec {
|
||||
# The sources, i.e. the attribute set of spec name to spec
|
||||
inherit sources;
|
||||
|
||||
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
|
||||
inherit pkgs;
|
||||
};
|
||||
|
||||
in
|
||||
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
|
||||
@@ -1,570 +0,0 @@
|
||||
\documentclass{beamer}
|
||||
%from https://www.overleaf.com/learn/latex/Beamer
|
||||
%Information to be included in the title page:
|
||||
\title{Efficient compilation of a functional Lisp based on Vau calculus}
|
||||
\author{Nathan Braswell}
|
||||
\institute{Georgia Tech}
|
||||
\date{2022}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\frame{\titlepage}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Combiners and Vau Introduction}
|
||||
Motivation and examples
|
||||
\begin{enumerate}
|
||||
\item<1-> Vau/Combiners unify and make first class functions, macros, and built-in forms in a single simple system
|
||||
\item<2-> They are also much simpler conceptually than macro systems, which often end up quite complex (Racket has positive and negative evaluation levels, etc)
|
||||
\item<3-> Downside: naively executing a language using combiners instead of macros is exceedingly slow
|
||||
\begin{enumerate}
|
||||
\item<4-> The code of the fexpr (analogus to a macro invocation) is re-executed at runtime, every time it is encountered
|
||||
\item<5-> 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.
|
||||
\end{enumerate}
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Solution: Partial Eval}
|
||||
\begin{enumerate}
|
||||
\item<1-> Partially evaluate a purely functional version of this language in a nearly-single pass over the entire program
|
||||
\item<2-> Environment chains consisting of both "real" environments with every contained symbol mapped to a value and "fake" environments that only have placeholder values.
|
||||
\item<3-> Since the language is purely functional, we know that if a symbol evaluates to a value anywhere, it will always evaluate to that value at runtime, and we can perform inlining and continue partial evaluation.
|
||||
\item<4-> If the resulting partially-evaluated program only contains static references to a subset of built in combiners and functions (combiners that evaluate their parameters exactly once), the program can be compiled just like it was a normal Scheme program
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Example time!}
|
||||
\begin{enumerate}
|
||||
\item<1-> We will wrap angle brackets $<>$ around values that are not representable in the syntax of the language - i.e. $+$ is a symbol that will be looked up in an environment, $<+>$ is the addition function.
|
||||
\item<2-> We will use square brackets $[]$ to indiciate array values, and we will use a single quote to indicate symbol values $'$, for instance $'+$ is the symbol $+$ as a value.
|
||||
\item<3-> Additionally, we will use curly braces ($\{\}$) to indicate the environment (mapping symbols to values). Elipses will be used to omit unnecessary information.
|
||||
\item<4-> Finally, we will not show the static environment nested in combiners, but know that each combiner carries with it the environment it was created with, which becomes the upper environment when its body is executing (the immediate environment being populated with the parameters).
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{A few more things..}
|
||||
\begin{enumerate}
|
||||
\item<1-> ; is the comment character for the language
|
||||
\item<2-> We will sometimes make larger evaluation jumps for (some) brevity
|
||||
\item<3-> wraplevel is how many times a combiner will evaluate its parameters before the body starts executing. 0 makes it work like a macro, 1 is like a function, etc
|
||||
\item<4-> Wrap takes a combiner and returns the same combiner with an incremented wraplevel, unwrap does the reverese
|
||||
\item<5-> Typing these examples by hand is too finicky, next time they'll be autogenerated with color by the prototype partial evaluator!
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Smallest Example}
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ ...root environment...}
|
||||
(wrap (vau (n) (* n 2)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<wrap> (vau (n) (* n 2)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<wrap> (<vau> (n) (* n 2)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<wrap> <comb wraplevel=0 (n) (* n 2)>)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
<comb wraplevel=1 (n) (* n 2)>
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Small Example}
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ ...root environment...}
|
||||
((wrap (vau (n) (* n 2))) (+ 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> (vau (n) (* n 2))) (+ 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> (<vau> (n) (* n 2))) (+ 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> <comb wraplevel=0 (n) (* n 2)>) (+ 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<comb wraplevel=1 (n) (* n 2)> (+ 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<comb wraplevel=1 (n) (* n 2)> (<+> 2 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<comb wraplevel=1 (n) (* n 2)> 4)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{n: 4 | upper: {...root environment...}}
|
||||
(* n 2)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{n: 4 | upper: {...root environment...}}
|
||||
(<*> n 2)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{n: 4 | upper: {...root environment...}}
|
||||
(<*> 4 2)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
8
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Small Vau-specific Example (implementing quote)}
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ ...root environment...}
|
||||
((vau (x) x) hello)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ ...root environment...}
|
||||
((<vau> (x) x) hello)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ ...root environment...}
|
||||
(<comb wraplevel=0 (x) x> hello)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{ x: 'hello | upper: {...root env....}}
|
||||
x
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
'hello
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\frametitle{Larger Example}
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...root environment...}
|
||||
((wrap (vau (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de))
|
||||
de)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> (vau (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de))
|
||||
de)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> (<vau> (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de))
|
||||
de)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
((<wrap> <comb wraplevel=0 (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
>) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de))
|
||||
de)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<comb wraplevel=1 (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
> (vau de (s v b) (eval (array (array vau (array s) b) (eval v de))
|
||||
de)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{...}
|
||||
(<comb wraplevel=1 (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
> <comb wraplevel=0 de (s v b) (eval (array (array vau (array s) b)
|
||||
(eval v de)) de)>)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{let1: <comb wraplevel=0 de (s v b)
|
||||
(eval (array (array vau (array s) b) (eval v de)) de)> | upper: {...}}
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2)))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{let1: ... | upper: {...}}
|
||||
(<comb wraplevel=0 de (s v b) (eval (array (array vau (array s) b)
|
||||
(eval v de)) de)>
|
||||
lambda
|
||||
(vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
Note the de in the environment being the environment the combiner was called in,
|
||||
as well as the current environment's upper being not the environment with let, but
|
||||
the root environment (the static environment from the function's creation).
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{s: 'lambda,
|
||||
v: ['vau 'se ['p 'b1] ['wrap ['eval ['array 'vau 'p 'b1] 'se]]],
|
||||
b: ['lambda ['n] ['* 'n 2]]
|
||||
de: {let1: ... | upper: {root...}} | upper: {root...}}
|
||||
(eval (array (array vau (array s) b) (eval v de)) de)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{s: 'lambda,
|
||||
v: ['vau 'se ['p 'b1] ['wrap ['eval ['array 'vau 'p 'b1] 'se]]],
|
||||
b: ['lambda ['n] ['* 'n 2]]
|
||||
de: {let1: ... | upper: {root...}} | upper: {root...}}
|
||||
(<eval> (array (array vau (array s) b) (eval v de)) de)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{s: 'lambda,
|
||||
v: ['vau 'se ['p 'b1] ['wrap ['eval ['array 'vau 'p 'b1] 'se]]],
|
||||
b: ['lambda ['n] ['* 'n 2]]
|
||||
de: {let1: ... | upper: {root...}} | upper: {root...}}
|
||||
(<eval> (<array> (array vau (array s) b) (eval v de)) de)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{s: 'lambda,
|
||||
v: ['vau 'se ['p 'b1] ['wrap ['eval ['array 'vau 'p 'b1] 'se]]],
|
||||
b: ['lambda ['n] ['* 'n 2]]
|
||||
de: {let1: ... | upper: {root...}} | upper: {root...}}
|
||||
(<eval> (<array> (<array> vau (array s) b) (eval v de)) de)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
Ok, evaluating all parameters of the array at the same time to be (slightly) consise.
|
||||
Note the replacement of de with the de environment, and that (eval v de) was fully executed to it's value. We'll see what the execution inside of eval looks like in a minute.
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{s: 'lambda,
|
||||
v: ['vau 'se ['p 'b1] ['wrap ['eval ['array 'vau 'p 'b1] 'se]]],
|
||||
b: ['lambda ['n] ['* 'n 2]]
|
||||
de: {let1: ... | upper: {root...}} | upper: {root...}}
|
||||
(<eval> (<array> (<array> <vau> ['lambda] ['lambda ['n] ['* 'n 2]])
|
||||
<comb wraplevel=0 se (p b1) (wrap (eval (array vau p b1)
|
||||
se))>) {let1: ...
|
||||
| upper: {root...}})
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
Again, let's take a few steps til we get the arrays as values
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
(<eval> [ [ <vau> ['lambda] ['lambda ['n] ['* 'n 2]]]
|
||||
<comb wraplevel=0 se (p b1) (wrap (eval (array vau p b1)
|
||||
se))>] {let1: ...
|
||||
| upper: {root...}})
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
Note that now that we are inside the eval call, our environment has swapped
|
||||
to that specified in the call.
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{let1: ... | upper: {root...}}
|
||||
( ( <vau> (lambda) (lambda (n) (* n 2)))
|
||||
<comb wraplevel=0 se (p b1) (wrap (eval (array vau p b1) se))>)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{let1: ... | upper: {root...}}
|
||||
( <comb wraplevel=0 (lambda) (lambda (n) (* n 2))>
|
||||
<comb wraplevel=0 se (p b1) (wrap (eval (array vau p b1) se))>)
|
||||
\end{verbatim}
|
||||
Ok, finally the let1 has reduced to a function application
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{lambda: <comb wraplevel=0 se (p b1)
|
||||
(wrap (eval (array vau p b1) se))>
|
||||
| upper: {let1: ... }}
|
||||
(lambda (n) (* n 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{lambda: ...}
|
||||
(<comb wraplevel=0 se (p b1) (wrap (eval (array vau p b1) se))>
|
||||
(n) (* n 2))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{p: ['n],
|
||||
b1: ['* 'n 2],
|
||||
se:{lambda: ...} | upper: {let1: ...}}
|
||||
(wrap (eval (array vau p b1) se))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{p: ['n],
|
||||
b1: ['* 'n 2],
|
||||
se:{lambda: ...} | upper: {let1: ...}}
|
||||
(<wrap> (eval (array vau p b1) se))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
We'll evaluate a few parameters at a time again
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{p: ['n],
|
||||
b1: ['* 'n 2],
|
||||
se:{lambda: ...} | upper: {let1: ...}}
|
||||
(<wrap> (<eval> (<array> <vau> ['n] ['* 'n 2]) {lambda: ...}))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{p: ['n],
|
||||
b1: ['* 'n 2],
|
||||
se:{lambda: ...} | upper: {let1: ...}}
|
||||
(<wrap> (<eval> [<vau> ['n] ['* 'n 2]] {lambda: ...}))
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
{p: ['n],
|
||||
b1: ['* 'n 2],
|
||||
se:{lambda: ...} | upper: {let1: ...}}
|
||||
(<wrap> <comb wraplevel=0 (n) (* n 2)>)
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
<comb wraplevel=1 (n) (* n 2)>
|
||||
\end{verbatim}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Conclusion: slow}
|
||||
\begin{enumerate}
|
||||
\item<1-> Look at all of the steps it took to simply get a function value that multiplies by 2!
|
||||
\item<2-> This would make our program much slower if this happened at runtime, for every function in the program.
|
||||
\item<3-> What's the solution? Partial Evaluation!
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Partial Eval: How it works}
|
||||
\begin{enumerate}
|
||||
\item<1-> Evaluate as much as possible ahead of time, at compile time.
|
||||
\item<2-> If some call sites are indeterminate, they can still be compiled, but there will have to be a runtime check inserted that splits evaluation based on if the combiner evaluates its parameters or not, and eval and all builtins will have to be compiled into the resulting executable.
|
||||
\item<3-> When compiling in the wraplevel=1 side of conditional, further partial evaluate the parameter value
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}[fragile]
|
||||
Partial evaluation could have done all the work from that last big example at compile time, leaving only the final value to be compiled:
|
||||
\footnotesize
|
||||
\begin{verbatim}
|
||||
<comb wraplevel=1 (n) (* n 2)>
|
||||
\end{verbatim}
|
||||
Additionally, if this was a more complex function that used other functions, those functions would also generally be fully partially evaluated at compile time.
|
||||
It's the full power of Vau/Combiners/Fexprs with the expected runtime performance of Scheme!
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Partial Eval: Current Status}
|
||||
\begin{enumerate}
|
||||
\item<1-> No longer *super* slow
|
||||
\item<2-> Fixed most BigO algo problems (any naive traversal is exponential)
|
||||
\item<3-> Otherwise, the implementation is slow (pure function, Chicken Scheme not built for it, mostly un-profiled and optimized, etc)
|
||||
\item<4-> Compiles wraplevel=0 combs to a assert(false), but simple to implement.
|
||||
\item<5-> Working through bugs - right now figuring out why some things don't partially evaluate as far as they should
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\frametitle{Partial Eval: Future: Type System Hints}
|
||||
Allow type systems to be built using Vaus, like the type-systems-as-macros paper (\url{https://www.ccs.neu.edu/home/stchang/pubs/ckg-popl2017.pdf}).
|
||||
This type system could pass down type hints to the partial evaluator, enabling:
|
||||
\begin{enumerate}
|
||||
\item<2-> Compiletime: Drop optimizing compiled version if wraplevel=0
|
||||
\item<3-> Compiletime: Drop emitting constant code for if wraplevel=1
|
||||
\item<4-> Runtime: Eliminate branch on wrap level
|
||||
\item<5-> Runtime: Eliminate other typechecks for builtin functions
|
||||
\end{enumerate}
|
||||
\end{frame}
|
||||
|
||||
\end{document}
|
||||
@@ -1,306 +0,0 @@
|
||||
|
||||
Key Contributions to look out for that make this work in practical time:
|
||||
1. First class environments that:
|
||||
a. Have IDs
|
||||
b. Can either be "real", in which case it maps symbols to values,
|
||||
or "fake", in which case it maps symbols to themselves, but with the env ID as it's for-progress
|
||||
c. Chain up to an upper environment that may be fake or real
|
||||
2. AST nodes that maintain on-node:
|
||||
a. The IDs of environments that, if "real", can be used to make progress in this subtree
|
||||
b. The hashes of infinite recursive calls that were detected and stopped - if this hash isn't in the current call chain, this subtree can make progress
|
||||
c. Extra IDs of environments that are "real" but have "fake" environments in their chain - this is used to make return value checking fast O(1 or log n, depending)
|
||||
3. Combiners, both user-defined and built in (including that maintain a "wrap level" that:
|
||||
a. Is a property of this function value, *not* the function itself
|
||||
* meaning that if wrap_level > 1, you can evaluate each parameter and decrement wrap_level, even if you can't execute the call
|
||||
4. The return value of a combiner is checked for:
|
||||
a. If it is a value, in which case it is good to be returned if it doesn't contain a reference to the envID of the function it is being returned from
|
||||
b. If it is (veval something env) where env doesn't contain a reference to the envID of the function it is being returned from
|
||||
c. If it is a call to a function (func params...) and func doesn't take in a dynamic environment and params... are all good to be returned
|
||||
This makes it so that combiner calls can return partially-evaluated code - any macro-like combiner would calculate the new code and return
|
||||
(eval <constructed-code> dynamic_env), which would do what partial evaluation it could and either become a value or a call like case "b" above.
|
||||
Case "b" allows this code essentially "tagged" with the environment it should be evaluated in to be returned out of "macro-like" combiners,
|
||||
and this dovetails with the next point
|
||||
5. The (veval something env) form essentially "tags" a piece of code with the environment it should be evaluated in. At each stage where
|
||||
it is possible, the system checks for redundent constructions like these, where the env in (veval something env) is the currently active env.
|
||||
In this case, it unwraps it to just "something" and continues on - this completes the second half of the macro-like combiner evaluation where
|
||||
after being returned to the calling function the code is essentially spliced in.
|
||||
6. The compiler can emit if/else branches on the wrap_level of combiners and in each branch further compile/partial eval if appropriate, allowing
|
||||
dynamic calls to either functions or combiners with the overhead of a single branch
|
||||
|
||||
Note that points 4&5 make it so that any macro written as a combiner in "macro-style" will be expanded just like a macro would and cause no runtime overhead!
|
||||
Additionally, point 6 makes it so that functions (wrap level 1 combiners) and non-parameter-evaluating (wrap level 0) combiners can be dynamically passed around and called with very minimal overhead.
|
||||
Combine them together and you get a simpler but more flexiable semantics than macro based (pure functional) languages with little-to-no overhead.
|
||||
|
||||
Additional tricky spots to look out for:
|
||||
1. If you don't do the needed-for-progress tracking, you have exponential runtime
|
||||
2. If you aren't careful about storing analysis information on the AST node itself or memoize, a naive tree traversal of the DAG has exponential runtime
|
||||
3. Infinite recursion can hide in sneaky places, including the interply between the partial evaluator and the compiler, and careful use of multiple recursion blockers / memoization is needed to prevent all cases
|
||||
4. The invarients needed to prevent mis-evaluation are non-trivial to get right. Our invarients:
|
||||
a. All calls to user-combiners have the parameters as total values, thus not moving something that needs a particular environment underneath a different environment
|
||||
b. All return values from functions must not depend on the function's environment (there are a couple of interesting cases here, see combiner_return_ok(func_result, env_id))
|
||||
c. All array values are made up of total values
|
||||
d. Some primitive combiners don't obey "a", but they must be written with extreme care, and often partially evaluate only some of their parameters and have to keep track of which.
|
||||
|
||||
|
||||
|
||||
Everything operates on AST nodes, an ADT:
|
||||
* val - integers, strings, booleans
|
||||
* marked_array
|
||||
* marked_symbol
|
||||
* comb
|
||||
* prim_comb
|
||||
* marked_env
|
||||
|
||||
Each AST node contains a hash representing it&it's subtree.
|
||||
|
||||
fun needed_for_progress(ast_node) -> (progress_IDs, rec_stopping_hashes, extra_IDs):
|
||||
returns
|
||||
- environment IDs (stored in each AST node for it and it's children)
|
||||
that must have real values if the partial evaluation of the subtree rooted at
|
||||
this node is going to make progress partial evaluating.
|
||||
|
||||
progress_IDs is either true (meaning it will make progress no matter what), an
|
||||
intset of env IDs (the ones that will cause it to make progress), or an empty
|
||||
set, meaning it can't make forward progress no matter what
|
||||
- hashes that if you're not inside the evaluation of, it could make progress
|
||||
- extra IDs for envs it contains that don't count as forward progress IDs because the
|
||||
env does have values, but envs in it's parent chain doesn't have values.
|
||||
|
||||
The calculation for needed_for_progress is straightforward-ish, with some tricky bits at comb and array.
|
||||
|
||||
Under these definitions, we call an AST subtree a "total val" if it is either a val or it's needed-for-progress IDs is nil.
|
||||
|
||||
fun mark(x, eval_pos):
|
||||
x is env -> error
|
||||
x is combiner -> error
|
||||
x is symbol -> if x == true than MarkedVal(true)
|
||||
else if x == false than MarkedVal(false)
|
||||
else MarkedSymbol(x, needed_IDs=if eval_pos true else nil)
|
||||
x is array ->
|
||||
MarkedArray(is_val=!eval_pos, attempted=false, resume_hashes=nil,
|
||||
values = [mark(x[0], eval_pos)] + [mark(xi, false) for xi in x[1:]])
|
||||
true -> MarkedVal(x)
|
||||
|
||||
fun strip(x) -> value:
|
||||
if X is an AST node representing a value, it returns the value.
|
||||
May strip recursively in the case of an array value, etc.
|
||||
Errors on env, comb (but not prim_comb!) non value symbols or arrays
|
||||
|
||||
fun try_unval(x) -> Result<ASTNode>:
|
||||
//Removes one level of "value-ness".
|
||||
x is Array -> if !x.array_is_val Error()
|
||||
else Ok(MarkedArray(is_value=false,
|
||||
values = [try_unval(x.values[0])] + x.values[1:]))
|
||||
x is Symbol -> if !x.symbol_is_val Error()
|
||||
else Ok(MarkedSymbol(symbol=x.symbol, is_value=false))
|
||||
true -> Ok(x)
|
||||
|
||||
fun check_for_env_id_in_result(env_id, x):
|
||||
return env_id in <either progress_IDs or extra_IDs in needed_for_progress(x)>
|
||||
if either progress_IDs or extra_IDs is true, then we have a fallback, but
|
||||
that doesn't get called even on large testcases so it's either rare or impossible.
|
||||
Fallback is slow though, whereas this is just a check for set membership
|
||||
|
||||
// We only allow returning a value out of a combiner if the return value
|
||||
// doesn't reference the environment of the combiner
|
||||
fun combiner_return_ok(func_result, env_id):
|
||||
func_result isn't later -> !check_for_env_id_in_result(env_id, func_result)
|
||||
// special cases now
|
||||
(veval body {env}) => (combiner_return_ok {env})
|
||||
// The reason we don't have to check body is that this form is only creatable in ways that body was origionally a value and only need {env}
|
||||
// Either it's created by eval, in which case it's fine, or it's created by something like (eval (array veval x de) de2) and the array has checked it,
|
||||
// or it's created via literal vau invocation, in which case the body is a value.
|
||||
(func ...params) => func doesn't take dynamic env && all params are combiner_return_ok
|
||||
otherwise -> false
|
||||
|
||||
// We may end up in situations where the value/code we care about is wrapped up in
|
||||
// a redundent call to veval, namely after sucessfully returning based on combiner_return_ok above.
|
||||
// This call may prevent other optimizations though, so we should unwrap the redundent call if possible,
|
||||
// and if it causes a change we should re-partially-evaluate to make further progress if we can
|
||||
fun drop_redundent_veval(x, dynamic_env, env_stack, memostuff):
|
||||
(veval node env) if env.id == dynamic_env.id -> drop_redundent_veval(node, dynamic_env, env_stack, memostuff)
|
||||
(comb params...) if comb.wrap_level != -1 -> map drop_redundent_veval over params and if any change: partial_eval( (comb new_params...), dynamic_env, env_stack, memostuff)
|
||||
else: x
|
||||
else -> x
|
||||
|
||||
fun make_tmp_inner_env(params, de?, ue, env_id):
|
||||
...
|
||||
|
||||
|
||||
fun partial_eval_helper(x, only_head, env, env_stack, memostuff, force):
|
||||
needed, hashes, _extra = needed_for_partial_eval(x)
|
||||
if force || one of hashes is not in memostuff || needed == true || set_intersection(needed, env_stack.set_of_ids_that_are_vals) != empty_set:
|
||||
x is MarkedVal -> x
|
||||
x is MarkedEnv -> find(x.env_id == it.env_id, env_stack) ?: x
|
||||
x is MarkedComb -> if !env.is_real && !x.se.is_real // both aren't real, re-evaluation of closure creation site
|
||||
|| env.is_real && !x.se.is_real // new env real, but se isn't - the creation of the closure!
|
||||
then let inner_env = make_tmp_inner_env(x.params, x.de?, env, x.env_id)
|
||||
in MarkedComb(se=env, body=partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false))
|
||||
x is MarkedPrimComb -> x
|
||||
x is MarkedSymbol -> if x.is_val then x
|
||||
else env_lookup_helper(x, env)
|
||||
x is MarkedArray -> if x.is_val then x
|
||||
else let
|
||||
comb = partial_eval_helper(x.values[0], only_head=true, env, env_stack, memostuff, false)
|
||||
params = x.values[1:]
|
||||
if later_head?(comb) return MarkedArray(values=[comb]+params)
|
||||
if comb.needed_for_progress == true:
|
||||
comb = partial_eval_helper(comb, only_head=false, ...)
|
||||
|
||||
// If not -1, we always partial eval, if >0 we also unval/partial eval to do one full round of eval
|
||||
wrap_level = comb.wrap_level
|
||||
while wrap_level >= 0:
|
||||
if wrap_level >= 1:
|
||||
params = map(unval, map(\x. partial_eval_helper(x, ...), params))
|
||||
params = map(\x. partial_eval_helper(x, ...), params)
|
||||
wrap_level -= 1
|
||||
if <any of the above error, or couldn't be unvaled yet>:
|
||||
return MarkedArray(values=[comb.with_wrap_level(wrap_level)] + <params at whatever level they were sucessfully evaluated to>)
|
||||
|
||||
if comb is MarkedPrimComb:
|
||||
result = comb.impl(params)
|
||||
if result == 'LATER:
|
||||
return MarkedArray(values=[comb.with_wrap_level(wrap_level)] + params)
|
||||
else:
|
||||
return result
|
||||
|
||||
if comb.is_varadic:
|
||||
params = params[:comb.params.len-1] + [ params[comb.params.len-1:] ]
|
||||
|
||||
inner_env = MarkedEnv(id=comb.env_id, possible_de_symbol=comb.de?, possible_de=env, symbols=comb.params, values=params, upper=comb.se)
|
||||
|
||||
rec_stop_hash = combine_hash(inner_env.hash, comb.body.hash)
|
||||
if rec_stop_hash in memostuff:
|
||||
return MarkedArray(values=[comb] + params, transient_needed_env_id=true, rec_stopping_hash=rec_stop_hash)
|
||||
|
||||
memostuff.add(rec_stop_hash)
|
||||
result = partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false)
|
||||
memostuff.remove(rec_stop_hash)
|
||||
|
||||
if !combiner_return_ok(result, comb.env_id):
|
||||
transiently_needed = if comb.de? != nil then env.id else nil
|
||||
return MarkedArray(values=[comb] + params, transient_needed_env_id=transiently_needed, rec_stopping_hash=rec_stop_hash)
|
||||
|
||||
return drop_redundent_veval(result, env, env_stack, memostuff)
|
||||
|
||||
And then we define a root_env with PrimComb versions of all of the standard functions.
|
||||
The ones that are most interesting and interact the most with partial evaluation are
|
||||
vau eval cond
|
||||
The other key is that array only takes in values, that is an array value never hides something that isn't a total value and needs more partial-evaluation
|
||||
(this makes a lot of things simpler in other places since we can treat array values as values no matter what and know things aren't hiding in sneaky places)
|
||||
|
||||
fun needs_params_prim(...):
|
||||
...
|
||||
fun give_up_params_prim(...):
|
||||
...
|
||||
|
||||
fun veval_inner(only_head, de, env_stack, memostuff, params):
|
||||
body = params[0]
|
||||
implicent_env = len(params) != 2
|
||||
eval_env = if implicit_env { de } else { partial_eval_helper(params[1], only_head, de, env_stack, memostuff, false) }
|
||||
evaled_body = partial_eval_helper(body, only_head, eval_env, env_stack, memostuff, false)
|
||||
if implicit_env or combiner_return_ok(evaled_body, eval_env.idx):
|
||||
return drop_redundent_veval(evaled_body, de, env_stack, memostuff)
|
||||
else:
|
||||
return drop_redundent_veval(MarkedArray(values=[MarkedPrimComb('veval, wrap_level=-1, val_head_ok=true, handler=veval_inner), evaled_body, eval_env], de, env_stack, memostuff)
|
||||
|
||||
root_env = {
|
||||
eval: MarkedPrimComb('eval, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, params):
|
||||
let
|
||||
body = params[0]
|
||||
implicit_env = len(params) != 2
|
||||
return veval_inner(only_head, de, env_stack, memostuff, if implicit_env { [try_unval(body)] } else { [try_unval(body), params[1]] })
|
||||
)
|
||||
vapply: MarkedPrimComb('vapply, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, [func params env]):
|
||||
return veval_inner(only_head, de, env_stack, memostuff, [MarkedArray(values=[func]+params), env)
|
||||
)
|
||||
lapply: MarkedPrimComb('lapply, wrap_level=1, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, [func params env]):
|
||||
return veval_inner(only_head, de, env_stack, memostuff, [MarkedArray(values=[func.offset_wrap_level(-1)]+params), env)
|
||||
)
|
||||
vau: MarkedPrimComb('vau, wrap_level=0, val_head_ok=true, handler=lambda(only_head, de, env_stack, memostuff, params):
|
||||
let
|
||||
de? = if len(params) == 3 { params[0].symbol_value } else { nil }
|
||||
params = map(lambda(x): s.symbol_value, if de? { params[1] } else { params[0] })
|
||||
varadic = '& in params
|
||||
params.remove('&)
|
||||
implicit_env = len(params) != 2
|
||||
body = try_unval(if de? { params[2] } else { params[1] })
|
||||
env_id = <new_id>
|
||||
if !only_head:
|
||||
inner_env = make_tmp_inner_env(params, de?, upper=de, id=env_id)
|
||||
body = partial_eval_helper(body, false, inner_env, <add inner_env to env_stack>, memostuff, false)
|
||||
return MarkedComb(wrap_level=0, id=new_id, de?=de?, static_env=de, variadic=varadic, params=params, body=body)
|
||||
)
|
||||
wrap: ...<returns new MarkedPrimComb/MarkedComb with incremented wrap_level>...
|
||||
unwrap: ...<returns new MarkedPrimComb/MarkedComb with decremented wrap_level>...
|
||||
cond: ...
|
||||
...Oddly tricky - is wrap_level 0, but...
|
||||
... 1. unvals & partially evaluates starting from the first condition
|
||||
... 2. if this condition is true, return the unvald & partially evaluated corresponding arm
|
||||
... 3. if this condition is false, drop the arm and return to 1
|
||||
... 4. In this case, we have an unknown between true & false
|
||||
... 5. check to see if combine_hash(x.hash, env.hash) is in memostuff (prevent infinite recursion blocked on a cond guard!)
|
||||
... 6. if the hash was in memostuff, return MarkedArray(later_hash=the_hash,
|
||||
... values=[MarkedPrimComb('vcond,wraplevel=-1,...)] + map(unval, <remaining preds/arms>))
|
||||
... 7. else new_preds_arms = map(partial_eval..., map(unval, <remaining preds/arms>))
|
||||
... <TODO: 8. remove arms/preds now guarenteed to be false, remove all arms/preds after first true>
|
||||
... 9. return MarkedArray(values=[MarkedPrimComb('vcond,wraplevel=-1,...)] + new_preds)
|
||||
...
|
||||
...The vcond is like cond but doesn't do any unvaling (as it's already been done) (and wrap_level is set to -1 so the function call machinery doesn't touch the params either)
|
||||
...
|
||||
symbol?: needs_params_prim(symbol?)
|
||||
int?: needs_params_prim(int?)
|
||||
string?: needs_params_prim(string?)
|
||||
combiner?: ...
|
||||
env?: ...
|
||||
nil?: needs_params_prim(nil?)
|
||||
bool?: needs_params_prim(bool?)
|
||||
str-to-symbol: needs_params_prim(str-to-symbol)
|
||||
get-text: needs_params_prim(get-text)
|
||||
array?: ...
|
||||
array: ...
|
||||
len: ...
|
||||
idx: ...
|
||||
slice: ...
|
||||
concat: ...
|
||||
+: needs_params_prim(+)
|
||||
-: needs_params_prim(-)
|
||||
*: needs_params_prim(*)
|
||||
/: needs_params_prim(/)
|
||||
%: needs_params_prim(%)
|
||||
band: needs_params_prim(band)
|
||||
bor: needs_params_prim(bor)
|
||||
bnot: needs_params_prim(bnot)
|
||||
bxor: needs_params_prim(bxor)
|
||||
<<: needs_params_prim(<<)
|
||||
>>: needs_params_prim(>>)
|
||||
=: needs_params_prim(=)
|
||||
!=: needs_params_prim(!=)
|
||||
<: needs_params_prim(<)
|
||||
<=: needs_params_prim(<=)
|
||||
>: needs_params_prim(>)
|
||||
>=: needs_params_prim(>=)
|
||||
str: needs_params_prim(true_str)
|
||||
log: give_up_params_prim(log)
|
||||
error: give_up_params_prim(error)
|
||||
read-string: needs_params_prim(read-string)
|
||||
empty_env: MarkedEnv()
|
||||
}
|
||||
|
||||
fun compile(...):
|
||||
...
|
||||
... tagged words, etc
|
||||
... eval
|
||||
... vau / vau helper closure
|
||||
...
|
||||
Note that when it's compiling a call, it compiles an if/else chain on the wrap level of the combiner being called.
|
||||
in the 0 branch, it emits the parameters as constant data
|
||||
in the 1 branch, it unval's and partial evals all of the parameters before compiling them.
|
||||
- note that this must be robust to partial-eval errors, as this branch might not ever happen at runtime and be nonsense code!
|
||||
- if the partial evaluation errors, it emits a value that will cause an error at runtime into the compiled code
|
||||
in the > 1 branch, it errors
|
||||
...
|
||||
...
|
||||
Must be careful about infiniate recursion, including tricky cases that infinitly ping back and forth between
|
||||
partial eval and compile even though both have individual internal recursion checks
|
||||
...
|
||||
@@ -1,11 +0,0 @@
|
||||
let
|
||||
sources = import ./nix/sources.nix;
|
||||
pkgs = import sources.nixpkgs { };
|
||||
in
|
||||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
texlive.combined.scheme-full
|
||||
evince
|
||||
];
|
||||
}
|
||||
|
||||
263
doc/writeup.tex
@@ -1,263 +0,0 @@
|
||||
%%
|
||||
%% This is file `sample-acmsmall.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% samples.dtx (with options: `acmsmall')
|
||||
%%
|
||||
%% IMPORTANT NOTICE:
|
||||
%%
|
||||
%% For the copyright see the source file.
|
||||
%%
|
||||
%% Any modified versions of this file must be renamed
|
||||
%% with new filenames distinct from sample-acmsmall.tex.
|
||||
%%
|
||||
%% For distribution of the original source see the terms
|
||||
%% for copying and modification in the file samples.dtx.
|
||||
%%
|
||||
%% This generated file may be distributed as long as the
|
||||
%% original source files, as listed above, are part of the
|
||||
%% same distribution. (The sources need not necessarily be
|
||||
%% in the same archive or directory.)
|
||||
%%
|
||||
%%
|
||||
%% Commands for TeXCount
|
||||
%TC:macro \cite [option:text,text]
|
||||
%TC:macro \citep [option:text,text]
|
||||
%TC:macro \citet [option:text,text]
|
||||
%TC:envir table 0 1
|
||||
%TC:envir table* 0 1
|
||||
%TC:envir tabular [ignore] word
|
||||
%TC:envir displaymath 0 word
|
||||
%TC:envir math 0 word
|
||||
%TC:envir comment 0 0
|
||||
%%
|
||||
%%
|
||||
%% The first command in your LaTeX source must be the \documentclass command.
|
||||
\documentclass[acmsmall]{acmart}
|
||||
|
||||
%%
|
||||
%% \BibTeX command to typeset BibTeX logo in the docs
|
||||
\AtBeginDocument{%
|
||||
\providecommand\BibTeX{{%
|
||||
\normalfont B\kern-0.5em{\scshape i\kern-0.25em b}\kern-0.8em\TeX}}}
|
||||
|
||||
%% Rights management information. This information is sent to you
|
||||
%% when you complete the rights form. These commands have SAMPLE
|
||||
%% values in them; it is your responsibility as an author to replace
|
||||
%% the commands and values with those provided to you when you
|
||||
%% complete the rights form.
|
||||
\setcopyright{acmcopyright}
|
||||
\copyrightyear{2022}
|
||||
\acmYear{2022}
|
||||
\acmDOI{10.1145/1122445.1122456}
|
||||
|
||||
|
||||
%%
|
||||
%% These commands are for a JOURNAL article.
|
||||
\acmJournal{JACM}
|
||||
\acmVolume{37}
|
||||
\acmNumber{4}
|
||||
\acmArticle{111}
|
||||
\acmMonth{8}
|
||||
|
||||
%%
|
||||
%% Submission ID.
|
||||
%% Use this when submitting an article to a sponsored event. You'll
|
||||
%% receive a unique submission ID from the organizers
|
||||
%% of the event, and this ID should be used as the parameter to this command.
|
||||
\acmSubmissionID{123-A56-BU3}
|
||||
|
||||
%%
|
||||
%% The majority of ACM publications use numbered citations and
|
||||
%% references. The command \citestyle{authoryear} switches to the
|
||||
%% "author year" style.
|
||||
%%
|
||||
%% If you are preparing content for an event
|
||||
%% sponsored by ACM SIGGRAPH, you must use the "author year" style of
|
||||
%% citations and references.
|
||||
%% Uncommenting
|
||||
%% the next command will enable that style.
|
||||
%%\citestyle{acmauthoryear}
|
||||
|
||||
%%
|
||||
%% end of the preamble, start of the body of the document source.
|
||||
\begin{document}
|
||||
|
||||
%%
|
||||
%% The "title" command has an optional parameter,
|
||||
%% allowing the author to define a "short title" to be used in page headers.
|
||||
\title{Efficient compilation of a functional Lisp based on Vau calculus}
|
||||
|
||||
%%
|
||||
%% The "author" command and its associated commands are used to define
|
||||
%% the authors and their affiliations.
|
||||
%% Of note is the shared affiliation of the first two authors, and the
|
||||
%% "authornote" and "authornotemark" commands
|
||||
%% used to denote shared contribution to the research.
|
||||
\author{Nathan Braswell}
|
||||
\email{nathan.braswell@gtri.@gatech.edu}
|
||||
%%\orcid{1234-5678-9012}
|
||||
%%\author{G.K.M. Tobin}
|
||||
%%\authornotemark[1]
|
||||
%%\email{webmaster@marysville-ohio.com}
|
||||
\affiliation{%
|
||||
\institution{Georgia Tech}
|
||||
%%\streetaddress{P.O. Box 1212}
|
||||
\city{Atlanta}
|
||||
\state{GA}
|
||||
\country{USA}
|
||||
%%\postcode{43017-6221}
|
||||
}
|
||||
|
||||
%%
|
||||
%% By default, the full list of authors will be used in the page
|
||||
%% headers. Often, this list is too long, and will overlap
|
||||
%% other information printed in the page headers. This command allows
|
||||
%% the author to define a more concise list
|
||||
%% of authors' names for this purpose.
|
||||
%%\renewcommand{\shortauthors}{Trovato and Tobin, et al.}
|
||||
|
||||
%%
|
||||
%% The abstract is a short summary of the work to be presented in the
|
||||
%% article.
|
||||
\begin{abstract}
|
||||
Vau and Fexprs, as formulated by John Shutt \cite{shutt2010fexprs}, provide a first class and more powerful alternative to
|
||||
macros. On the other hand, naively executing a language using Vau and Fexprs instead of macros is exceedingly slow,
|
||||
as the code of the fexpr (analogus to a macro invocation) is re-executed at runtime, every time it is encountered.
|
||||
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 a combiner, little optimization can be done. We address this problem with, to our knowledge,
|
||||
the first partial evaluation system that can completely optimize away fexprs that are used and written in the style of macros,
|
||||
as well as some other more naturally written combiners.
|
||||
\end{abstract}
|
||||
|
||||
%%
|
||||
%% The code below is generated by the tool at http://dl.acm.org/ccs.cfm.
|
||||
%% Please copy and paste the code instead of the example below.
|
||||
%%
|
||||
%%\begin{CCSXML}
|
||||
%%<ccs2012>
|
||||
%% <concept>
|
||||
%% <concept_id>10010520.10010553.10010562</concept_id>
|
||||
%% <concept_desc>Computer systems organization~Embedded systems</concept_desc>
|
||||
%% <concept_significance>500</concept_significance>
|
||||
%% </concept>
|
||||
%% <concept>
|
||||
%% <concept_id>10010520.10010575.10010755</concept_id>
|
||||
%% <concept_desc>Computer systems organization~Redundancy</concept_desc>
|
||||
%% <concept_significance>300</concept_significance>
|
||||
%% </concept>
|
||||
%% <concept>
|
||||
%% <concept_id>10010520.10010553.10010554</concept_id>
|
||||
%% <concept_desc>Computer systems organization~Robotics</concept_desc>
|
||||
%% <concept_significance>100</concept_significance>
|
||||
%% </concept>
|
||||
%% <concept>
|
||||
%% <concept_id>10003033.10003083.10003095</concept_id>
|
||||
%% <concept_desc>Networks~Network reliability</concept_desc>
|
||||
%% <concept_significance>100</concept_significance>
|
||||
%% </concept>
|
||||
%%</ccs2012>
|
||||
%%\end{CCSXML}
|
||||
|
||||
%%\ccsdesc[500]{Computer systems organization~Embedded systems}
|
||||
%%\ccsdesc[300]{Computer systems organization~Redundancy}
|
||||
%%\ccsdesc{Computer systems organization~Robotics}
|
||||
%%\ccsdesc[100]{Networks~Network reliability}
|
||||
|
||||
%%
|
||||
%% Keywords. The author(s) should pick words that accurately describe
|
||||
%% the work being presented. Separate the keywords with commas.
|
||||
\keywords{partial evaluation, vau, fexprs, WebAssembly}
|
||||
|
||||
|
||||
%%
|
||||
%% This command processes the author and affiliation and title
|
||||
%% information and builds the first part of the formatted document.
|
||||
\maketitle
|
||||
|
||||
\section{Introduction and Motivation}
|
||||
|
||||
Lisps generally have two different abstraction methods, functions and macros. Functions operate at runtime and always
|
||||
evaluate their parameters, while macros operate at compiletime and do not evaluate their parameters. This generally
|
||||
splits the language to a degree, and macros are not able to be used at runtime, though generally functions are
|
||||
able to be used in macros, with various restrictions. The macro systems generally attempt to be hygenic, either preventing
|
||||
or making it difficult to manipulate the environment of the code that the macro invocation will expand to. This is often
|
||||
needed, however, and various escape hatches can be implemented.
|
||||
|
||||
Creating a powerful, safe, and easy to use macro system is quite difficult, and the resulting systems are often quite complex,
|
||||
generally more complex than the base language in which the reside. Macros are also not first class, and cannot be passed
|
||||
around as values and do not exist at all at runtime.
|
||||
|
||||
Vau and Fexprs, as formulated by John Shutt \cite{shutt2010fexprs}, (at \url{https://web.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unrestricted/jshutt.pdf}),
|
||||
provide a first class and more powerful alternative to macros, unifying functions, macros, and built-in language forms
|
||||
into a single concept called a combiner. A combiner may evaluate its arguments 0 or more times,
|
||||
and recieves the calling environment as an additional parameter. There is also an eval function which takes in an expression to evaluate
|
||||
and an environment in which to do the evaluation. Note that functions, macros, and even built-in language constructs like if, cond, let can be implemented
|
||||
as either user-defined or built-in combiners, making both macros and what were previously Lisp special forms first class! They can be named,
|
||||
passed to higher-order combiners, put into datastructures, etc.
|
||||
|
||||
On the other hand, naively executing a language using combiners instead of macros is exceedingly slow,
|
||||
as the code of the fexpr (analogus to a macro invocation) is re-executed at runtime, every time it is encountered.
|
||||
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. We address this problem with, to our knowledge,
|
||||
the first partial evaluation system that can completely optimize away fexprs that are used and written in the style of macros,
|
||||
as well as some other more naturally written combiners. Our language is more restricted than Shutt's Kernel language, being
|
||||
purely functional and allowing no mutation, making the tracking of environments and optimization of access tractable.
|
||||
|
||||
All code available at \url{https://github.com/limvot/kraken}
|
||||
|
||||
\section{Prior Work}
|
||||
\begin{itemize}
|
||||
\item{} Axis of Eval list of 22 attempted implmentations - \url{https://axisofeval.blogspot.com/2011/09/kernel-underground.html} \\
|
||||
None doing partial evaluation, to my knowledge. I belive all abandond or linkrotted with the seeming exception of \url{https://github.com/rocketnia/fexpress},
|
||||
which is taking a very different approach (Lisp-2, explicit apply form, etc) in Racket.
|
||||
\item{} Lambda The Ultimate small discussion of partial eval for Vau/Kernel - \url{http://lambda-the-ultimate.org/node/4346}
|
||||
\item{} Implementing a Vau-based Language With Multiple Evaluation Strategies - \cite{kearsleyimplementing} \\
|
||||
Talks about how partial evaluation could make efficient, doesn't do it.
|
||||
\item{} Google Groups email thread by Andres Navarro - \url{https://groups.google.com/g/klisp/c/Dva-Le8Hr-g/m/pyl1Ufu-vksJ} \\
|
||||
Andres Navarro talks about his experimental fklisp which is a "very simple functional dialect of Kernel" with no mutation or first class continuations.
|
||||
It doesn't compile anything, but prints out the partially evalauted expression. Was a work in progress, ran into performance problems, seems abandond.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Issues}
|
||||
As described in the introduction, the main issue with basing a langauge off of Vau and combiners is slowness.
|
||||
This comes from two main problems: one, the combiners taking the place of macros are re-executed every time
|
||||
they are encountered instead of being expanded into intermediate code like in a macro system, and two, because
|
||||
the compiler in general cannot tell if the combiner being called takes in its parameters by value or not, it cannot
|
||||
do practically any optimization.
|
||||
|
||||
\section{Solution}
|
||||
We partially evaluate a purely function version of this language in a nearly-single pass over the entire program.
|
||||
We allow environment chains consisting of both "real" environments with every contained symbol mapped to a value and "fake" environments
|
||||
that only have placeholder values. Since the language is purely functional, we know that if a symbol evaluates to a value anywhere, it
|
||||
will always evaluate to that value at runtime. With this, we can notice most calls to combiners that don't evaluate their parameters
|
||||
(since if we can resolve the combiner to a value, we know that will always be the combiner called at that location) and we can perform
|
||||
inlining and continue partial evaluation.
|
||||
|
||||
If the resulting partially-evaluated program only contains static references to a subset of built in combiners and function (combiners that
|
||||
evaluate their parameters exactly once), the program can be compiled just like it was a normal Scheme program.
|
||||
If some call sites are indeterminate, they can still be compiled, but there will have to be a runtime check inserted that splits
|
||||
evaluation based on if the combiner evaluates its parameters or not, and eval and all builtins will have to be compiled into the resulting executable.
|
||||
|
||||
A Vau/combiner based language allows most of the language to be built up in the language itself, as combiners. For instance, even lambda and let
|
||||
are derived instead of primitive. See below, where we define both let1 (a simple version of let binding only one variable) and lambda.
|
||||
\begin{verbatim}
|
||||
((wrap (vau (let1)
|
||||
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(lambda (n) (* n 2))
|
||||
)
|
||||
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de)) de)))
|
||||
\end{verbatim}
|
||||
|
||||
\bibliographystyle{ACM-Reference-Format}
|
||||
\bibliography{cited-paper}
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sample-acmsmall.tex'.
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
fib (rec-lambda fib (n) (cond (= 0 n) 1
|
||||
(= 1 n) 1
|
||||
true (+ (fib (- n 1)) (fib (- n 2)))))
|
||||
|
||||
monad (array 'write 1 "enter number to fact: " (vau (written code)
|
||||
(array 'read 0 60 (vau (data code)
|
||||
(array 'exit (builtin_fib (read-string data)))
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
13
fib_test/clojure_fib/.gitignore
vendored
@@ -1,13 +0,0 @@
|
||||
/target
|
||||
/classes
|
||||
/checkouts
|
||||
profiles.clj
|
||||
pom.xml
|
||||
pom.xml.asc
|
||||
*.jar
|
||||
*.class
|
||||
/.lein-*
|
||||
/.nrepl-port
|
||||
/.prepl-port
|
||||
.hgignore
|
||||
.hg/
|
||||
@@ -1,280 +0,0 @@
|
||||
Eclipse Public License - v 2.0
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
|
||||
PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
|
||||
OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a) in the case of the initial Contributor, the initial content
|
||||
Distributed under this Agreement, and
|
||||
|
||||
b) in the case of each subsequent Contributor:
|
||||
i) changes to the Program, and
|
||||
ii) additions to the Program;
|
||||
where such changes and/or additions to the Program originate from
|
||||
and are Distributed by that particular Contributor. A Contribution
|
||||
"originates" from a Contributor if it was added to the Program by
|
||||
such Contributor itself or anyone acting on such Contributor's behalf.
|
||||
Contributions do not include changes or additions to the Program that
|
||||
are not Modified Works.
|
||||
|
||||
"Contributor" means any person or entity that Distributes the Program.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor which
|
||||
are necessarily infringed by the use or sale of its Contribution alone
|
||||
or when combined with the Program.
|
||||
|
||||
"Program" means the Contributions Distributed in accordance with this
|
||||
Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement
|
||||
or any Secondary License (as applicable), including Contributors.
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source Code or other
|
||||
form, that is based on (or derived from) the Program and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship.
|
||||
|
||||
"Modified Works" shall mean any work in Source Code or other form that
|
||||
results from an addition to, deletion from, or modification of the
|
||||
contents of the Program, including, for purposes of clarity any new file
|
||||
in Source Code form that contains any contents of the Program. Modified
|
||||
Works shall not include works that contain only declarations,
|
||||
interfaces, types, classes, structures, or files of the Program solely
|
||||
in each case in order to link to, bind by name, or subclass the Program
|
||||
or Modified Works thereof.
|
||||
|
||||
"Distribute" means the acts of a) distributing or b) making available
|
||||
in any manner that enables the transfer of a copy.
|
||||
|
||||
"Source Code" means the form of a Program preferred for making
|
||||
modifications, including but not limited to software source code,
|
||||
documentation source, and configuration files.
|
||||
|
||||
"Secondary License" means either the GNU General Public License,
|
||||
Version 2.0, or any later versions of that license, including any
|
||||
exceptions or additional permissions as identified by the initial
|
||||
Contributor.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare Derivative Works of, publicly display,
|
||||
publicly perform, Distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such Derivative Works.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor,
|
||||
if any, in Source Code or other form. This patent license shall
|
||||
apply to the combination of the Contribution and the Program if, at
|
||||
the time the Contribution is added by the Contributor, such addition
|
||||
of the Contribution causes such combination to be covered by the
|
||||
Licensed Patents. The patent license shall not apply to any other
|
||||
combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity.
|
||||
Each Contributor disclaims any liability to Recipient for claims
|
||||
brought by any other entity based on infringement of intellectual
|
||||
property rights or otherwise. As a condition to exercising the
|
||||
rights and licenses granted hereunder, each Recipient hereby
|
||||
assumes sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party
|
||||
patent license is required to allow Recipient to Distribute the
|
||||
Program, it is Recipient's responsibility to acquire that license
|
||||
before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has
|
||||
sufficient copyright rights in its Contribution, if any, to grant
|
||||
the copyright license set forth in this Agreement.
|
||||
|
||||
e) Notwithstanding the terms of any Secondary License, no
|
||||
Contributor makes additional grants to any Recipient (other than
|
||||
those set forth in this Agreement) as a result of such Recipient's
|
||||
receipt of the Program under the terms of a Secondary License
|
||||
(if permitted under the terms of Section 3).
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
3.1 If a Contributor Distributes the Program in any form, then:
|
||||
|
||||
a) the Program must also be made available as Source Code, in
|
||||
accordance with section 3.2, and the Contributor must accompany
|
||||
the Program with a statement that the Source Code for the Program
|
||||
is available under this Agreement, and informs Recipients how to
|
||||
obtain it in a reasonable manner on or through a medium customarily
|
||||
used for software exchange; and
|
||||
|
||||
b) the Contributor may Distribute the Program under a license
|
||||
different than this Agreement, provided that such license:
|
||||
i) effectively disclaims on behalf of all other Contributors all
|
||||
warranties and conditions, express and implied, including
|
||||
warranties or conditions of title and non-infringement, and
|
||||
implied warranties or conditions of merchantability and fitness
|
||||
for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all other Contributors all
|
||||
liability for damages, including direct, indirect, special,
|
||||
incidental and consequential damages, such as lost profits;
|
||||
|
||||
iii) does not attempt to limit or alter the recipients' rights
|
||||
in the Source Code under section 3.2; and
|
||||
|
||||
iv) requires any subsequent distribution of the Program by any
|
||||
party to be under a license that satisfies the requirements
|
||||
of this section 3.
|
||||
|
||||
3.2 When the Program is Distributed as Source Code:
|
||||
|
||||
a) it must be made available under this Agreement, or if the
|
||||
Program (i) is combined with other material in a separate file or
|
||||
files made available under a Secondary License, and (ii) the initial
|
||||
Contributor attached to the Source Code the notice described in
|
||||
Exhibit A of this Agreement, then the Program may be made available
|
||||
under the terms of such Secondary Licenses, and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of
|
||||
the Program.
|
||||
|
||||
3.3 Contributors may not remove or alter any copyright, patent,
|
||||
trademark, attribution notices, disclaimers of warranty, or limitations
|
||||
of liability ("notices") contained within the Program from any copy of
|
||||
the Program which they Distribute, provided that Contributors may add
|
||||
their own appropriate notices.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities
|
||||
with respect to end users, business partners and the like. While this
|
||||
license is intended to facilitate the commercial use of the Program,
|
||||
the Contributor who includes the Program in a commercial product
|
||||
offering should do so in a manner which does not create potential
|
||||
liability for other Contributors. Therefore, if a Contributor includes
|
||||
the Program in a commercial product offering, such Contributor
|
||||
("Commercial Contributor") hereby agrees to defend and indemnify every
|
||||
other Contributor ("Indemnified Contributor") against any losses,
|
||||
damages and costs (collectively "Losses") arising from claims, lawsuits
|
||||
and other legal actions brought by a third party against the Indemnified
|
||||
Contributor to the extent caused by the acts or omissions of such
|
||||
Commercial Contributor in connection with its distribution of the Program
|
||||
in a commercial product offering. The obligations in this section do not
|
||||
apply to any claims or Losses relating to any actual or alleged
|
||||
intellectual property infringement. In order to qualify, an Indemnified
|
||||
Contributor must: a) promptly notify the Commercial Contributor in
|
||||
writing of such claim, and b) allow the Commercial Contributor to control,
|
||||
and cooperate with the Commercial Contributor in, the defense and any
|
||||
related settlement negotiations. The Indemnified Contributor may
|
||||
participate in any such claim at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial
|
||||
product offering, Product X. That Contributor is then a Commercial
|
||||
Contributor. If that Commercial Contributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Contributor's responsibility
|
||||
alone. Under this section, the Commercial Contributor would have to
|
||||
defend claims against the other Contributors related to those performance
|
||||
claims and warranties, and if a court requires any other Contributor to
|
||||
pay any damages as a result, the Commercial Contributor must pay
|
||||
those damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
|
||||
TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
|
||||
PURPOSE. Each Recipient is solely responsible for determining the
|
||||
appropriateness of using and distributing the Program and assumes all
|
||||
risks associated with its exercise of rights under this Agreement,
|
||||
including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs
|
||||
or equipment, and unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
|
||||
SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
|
||||
PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE
|
||||
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against any entity
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that the
|
||||
Program itself (excluding combinations of the Program with other software
|
||||
or hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement,
|
||||
but in order to avoid inconsistency the Agreement is copyrighted and
|
||||
may only be modified in the following manner. The Agreement Steward
|
||||
reserves the right to publish new versions (including revisions) of
|
||||
this Agreement from time to time. No one other than the Agreement
|
||||
Steward has the right to modify this Agreement. The Eclipse Foundation
|
||||
is the initial Agreement Steward. The Eclipse Foundation may assign the
|
||||
responsibility to serve as the Agreement Steward to a suitable separate
|
||||
entity. Each new version of the Agreement will be given a distinguishing
|
||||
version number. The Program (including Contributions) may always be
|
||||
Distributed subject to the version of the Agreement under which it was
|
||||
received. In addition, after a new version of the Agreement is published,
|
||||
Contributor may elect to Distribute the Program (including its
|
||||
Contributions) under the new version.
|
||||
|
||||
Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
|
||||
receives no rights or licenses to the intellectual property of any
|
||||
Contributor under this Agreement, whether expressly, by implication,
|
||||
estoppel or otherwise. All rights in the Program not expressly granted
|
||||
under this Agreement are reserved. Nothing in this Agreement is intended
|
||||
to be enforceable by any entity that is not a Contributor or Recipient.
|
||||
No third-party beneficiary rights are created under this Agreement.
|
||||
|
||||
Exhibit A - Form of Secondary Licenses Notice
|
||||
|
||||
"This Source Code may also be made available under the following
|
||||
Secondary Licenses when the conditions for such availability set forth
|
||||
in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public
|
||||
License as published by the Free Software Foundation, either version 2
|
||||
of the License, or (at your option) any later version, with the GNU
|
||||
Classpath Exception which is available at
|
||||
https://www.gnu.org/software/classpath/license.html."
|
||||
|
||||
Simply including a copy of this Agreement, including this Exhibit A
|
||||
is not sufficient to license the Source Code under Secondary Licenses.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to
|
||||
look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
@@ -1,10 +0,0 @@
|
||||
(defproject clojure_fib "0.1.0-SNAPSHOT"
|
||||
:description "FIXME: write description"
|
||||
:url "http://example.com/FIXME"
|
||||
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
|
||||
:url "https://www.eclipse.org/legal/epl-2.0/"}
|
||||
:dependencies [[org.clojure/clojure "1.10.3"]]
|
||||
:main ^:skip-aot clojure-fib.core
|
||||
:target-path "target/%s"
|
||||
:profiles {:uberjar {:aot :all
|
||||
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
|
||||
@@ -1,14 +0,0 @@
|
||||
(ns clojure-fib.core
|
||||
(:gen-class))
|
||||
|
||||
(defn fib
|
||||
[n]
|
||||
(cond (= n 0) 1
|
||||
(= n 1) 1
|
||||
:else (+ (fib (- n 1)) (fib (- n 2)))))
|
||||
|
||||
(defn -main
|
||||
"I don't do a whole lot ... yet."
|
||||
[& args]
|
||||
(println "Enter to fib: ")
|
||||
(println "was " (fib (Integer/parseInt (read-line)))))
|
||||
13
fib_test/clojure_hi/.gitignore
vendored
@@ -1,13 +0,0 @@
|
||||
/target
|
||||
/classes
|
||||
/checkouts
|
||||
profiles.clj
|
||||
pom.xml
|
||||
pom.xml.asc
|
||||
*.jar
|
||||
*.class
|
||||
/.lein-*
|
||||
/.nrepl-port
|
||||
/.prepl-port
|
||||
.hgignore
|
||||
.hg/
|
||||
@@ -1,280 +0,0 @@
|
||||
Eclipse Public License - v 2.0
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
|
||||
PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
|
||||
OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a) in the case of the initial Contributor, the initial content
|
||||
Distributed under this Agreement, and
|
||||
|
||||
b) in the case of each subsequent Contributor:
|
||||
i) changes to the Program, and
|
||||
ii) additions to the Program;
|
||||
where such changes and/or additions to the Program originate from
|
||||
and are Distributed by that particular Contributor. A Contribution
|
||||
"originates" from a Contributor if it was added to the Program by
|
||||
such Contributor itself or anyone acting on such Contributor's behalf.
|
||||
Contributions do not include changes or additions to the Program that
|
||||
are not Modified Works.
|
||||
|
||||
"Contributor" means any person or entity that Distributes the Program.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor which
|
||||
are necessarily infringed by the use or sale of its Contribution alone
|
||||
or when combined with the Program.
|
||||
|
||||
"Program" means the Contributions Distributed in accordance with this
|
||||
Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement
|
||||
or any Secondary License (as applicable), including Contributors.
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source Code or other
|
||||
form, that is based on (or derived from) the Program and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship.
|
||||
|
||||
"Modified Works" shall mean any work in Source Code or other form that
|
||||
results from an addition to, deletion from, or modification of the
|
||||
contents of the Program, including, for purposes of clarity any new file
|
||||
in Source Code form that contains any contents of the Program. Modified
|
||||
Works shall not include works that contain only declarations,
|
||||
interfaces, types, classes, structures, or files of the Program solely
|
||||
in each case in order to link to, bind by name, or subclass the Program
|
||||
or Modified Works thereof.
|
||||
|
||||
"Distribute" means the acts of a) distributing or b) making available
|
||||
in any manner that enables the transfer of a copy.
|
||||
|
||||
"Source Code" means the form of a Program preferred for making
|
||||
modifications, including but not limited to software source code,
|
||||
documentation source, and configuration files.
|
||||
|
||||
"Secondary License" means either the GNU General Public License,
|
||||
Version 2.0, or any later versions of that license, including any
|
||||
exceptions or additional permissions as identified by the initial
|
||||
Contributor.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare Derivative Works of, publicly display,
|
||||
publicly perform, Distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such Derivative Works.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor,
|
||||
if any, in Source Code or other form. This patent license shall
|
||||
apply to the combination of the Contribution and the Program if, at
|
||||
the time the Contribution is added by the Contributor, such addition
|
||||
of the Contribution causes such combination to be covered by the
|
||||
Licensed Patents. The patent license shall not apply to any other
|
||||
combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity.
|
||||
Each Contributor disclaims any liability to Recipient for claims
|
||||
brought by any other entity based on infringement of intellectual
|
||||
property rights or otherwise. As a condition to exercising the
|
||||
rights and licenses granted hereunder, each Recipient hereby
|
||||
assumes sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party
|
||||
patent license is required to allow Recipient to Distribute the
|
||||
Program, it is Recipient's responsibility to acquire that license
|
||||
before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has
|
||||
sufficient copyright rights in its Contribution, if any, to grant
|
||||
the copyright license set forth in this Agreement.
|
||||
|
||||
e) Notwithstanding the terms of any Secondary License, no
|
||||
Contributor makes additional grants to any Recipient (other than
|
||||
those set forth in this Agreement) as a result of such Recipient's
|
||||
receipt of the Program under the terms of a Secondary License
|
||||
(if permitted under the terms of Section 3).
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
3.1 If a Contributor Distributes the Program in any form, then:
|
||||
|
||||
a) the Program must also be made available as Source Code, in
|
||||
accordance with section 3.2, and the Contributor must accompany
|
||||
the Program with a statement that the Source Code for the Program
|
||||
is available under this Agreement, and informs Recipients how to
|
||||
obtain it in a reasonable manner on or through a medium customarily
|
||||
used for software exchange; and
|
||||
|
||||
b) the Contributor may Distribute the Program under a license
|
||||
different than this Agreement, provided that such license:
|
||||
i) effectively disclaims on behalf of all other Contributors all
|
||||
warranties and conditions, express and implied, including
|
||||
warranties or conditions of title and non-infringement, and
|
||||
implied warranties or conditions of merchantability and fitness
|
||||
for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all other Contributors all
|
||||
liability for damages, including direct, indirect, special,
|
||||
incidental and consequential damages, such as lost profits;
|
||||
|
||||
iii) does not attempt to limit or alter the recipients' rights
|
||||
in the Source Code under section 3.2; and
|
||||
|
||||
iv) requires any subsequent distribution of the Program by any
|
||||
party to be under a license that satisfies the requirements
|
||||
of this section 3.
|
||||
|
||||
3.2 When the Program is Distributed as Source Code:
|
||||
|
||||
a) it must be made available under this Agreement, or if the
|
||||
Program (i) is combined with other material in a separate file or
|
||||
files made available under a Secondary License, and (ii) the initial
|
||||
Contributor attached to the Source Code the notice described in
|
||||
Exhibit A of this Agreement, then the Program may be made available
|
||||
under the terms of such Secondary Licenses, and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of
|
||||
the Program.
|
||||
|
||||
3.3 Contributors may not remove or alter any copyright, patent,
|
||||
trademark, attribution notices, disclaimers of warranty, or limitations
|
||||
of liability ("notices") contained within the Program from any copy of
|
||||
the Program which they Distribute, provided that Contributors may add
|
||||
their own appropriate notices.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities
|
||||
with respect to end users, business partners and the like. While this
|
||||
license is intended to facilitate the commercial use of the Program,
|
||||
the Contributor who includes the Program in a commercial product
|
||||
offering should do so in a manner which does not create potential
|
||||
liability for other Contributors. Therefore, if a Contributor includes
|
||||
the Program in a commercial product offering, such Contributor
|
||||
("Commercial Contributor") hereby agrees to defend and indemnify every
|
||||
other Contributor ("Indemnified Contributor") against any losses,
|
||||
damages and costs (collectively "Losses") arising from claims, lawsuits
|
||||
and other legal actions brought by a third party against the Indemnified
|
||||
Contributor to the extent caused by the acts or omissions of such
|
||||
Commercial Contributor in connection with its distribution of the Program
|
||||
in a commercial product offering. The obligations in this section do not
|
||||
apply to any claims or Losses relating to any actual or alleged
|
||||
intellectual property infringement. In order to qualify, an Indemnified
|
||||
Contributor must: a) promptly notify the Commercial Contributor in
|
||||
writing of such claim, and b) allow the Commercial Contributor to control,
|
||||
and cooperate with the Commercial Contributor in, the defense and any
|
||||
related settlement negotiations. The Indemnified Contributor may
|
||||
participate in any such claim at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial
|
||||
product offering, Product X. That Contributor is then a Commercial
|
||||
Contributor. If that Commercial Contributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Contributor's responsibility
|
||||
alone. Under this section, the Commercial Contributor would have to
|
||||
defend claims against the other Contributors related to those performance
|
||||
claims and warranties, and if a court requires any other Contributor to
|
||||
pay any damages as a result, the Commercial Contributor must pay
|
||||
those damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
|
||||
TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
|
||||
PURPOSE. Each Recipient is solely responsible for determining the
|
||||
appropriateness of using and distributing the Program and assumes all
|
||||
risks associated with its exercise of rights under this Agreement,
|
||||
including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs
|
||||
or equipment, and unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
|
||||
SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
|
||||
PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE
|
||||
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against any entity
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that the
|
||||
Program itself (excluding combinations of the Program with other software
|
||||
or hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement,
|
||||
but in order to avoid inconsistency the Agreement is copyrighted and
|
||||
may only be modified in the following manner. The Agreement Steward
|
||||
reserves the right to publish new versions (including revisions) of
|
||||
this Agreement from time to time. No one other than the Agreement
|
||||
Steward has the right to modify this Agreement. The Eclipse Foundation
|
||||
is the initial Agreement Steward. The Eclipse Foundation may assign the
|
||||
responsibility to serve as the Agreement Steward to a suitable separate
|
||||
entity. Each new version of the Agreement will be given a distinguishing
|
||||
version number. The Program (including Contributions) may always be
|
||||
Distributed subject to the version of the Agreement under which it was
|
||||
received. In addition, after a new version of the Agreement is published,
|
||||
Contributor may elect to Distribute the Program (including its
|
||||
Contributions) under the new version.
|
||||
|
||||
Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
|
||||
receives no rights or licenses to the intellectual property of any
|
||||
Contributor under this Agreement, whether expressly, by implication,
|
||||
estoppel or otherwise. All rights in the Program not expressly granted
|
||||
under this Agreement are reserved. Nothing in this Agreement is intended
|
||||
to be enforceable by any entity that is not a Contributor or Recipient.
|
||||
No third-party beneficiary rights are created under this Agreement.
|
||||
|
||||
Exhibit A - Form of Secondary Licenses Notice
|
||||
|
||||
"This Source Code may also be made available under the following
|
||||
Secondary Licenses when the conditions for such availability set forth
|
||||
in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public
|
||||
License as published by the Free Software Foundation, either version 2
|
||||
of the License, or (at your option) any later version, with the GNU
|
||||
Classpath Exception which is available at
|
||||
https://www.gnu.org/software/classpath/license.html."
|
||||
|
||||
Simply including a copy of this Agreement, including this Exhibit A
|
||||
is not sufficient to license the Source Code under Secondary Licenses.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to
|
||||
look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
@@ -1,10 +0,0 @@
|
||||
(defproject clojure_hi "0.1.0-SNAPSHOT"
|
||||
:description "FIXME: write description"
|
||||
:url "http://example.com/FIXME"
|
||||
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
|
||||
:url "https://www.eclipse.org/legal/epl-2.0/"}
|
||||
:dependencies [[org.clojure/clojure "1.10.3"]]
|
||||
:main ^:skip-aot clojure-hi.core
|
||||
:target-path "target/%s"
|
||||
:profiles {:uberjar {:aot :all
|
||||
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})
|
||||
@@ -1,7 +0,0 @@
|
||||
(ns clojure-hi.core
|
||||
(:gen-class))
|
||||
|
||||
(defn -main
|
||||
"I don't do a whole lot ... yet."
|
||||
[& args]
|
||||
(println "Hello, World!"))
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
int fib(n) {
|
||||
if (n == 0) {
|
||||
return 1;
|
||||
} else if (n == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
}
|
||||
int main(int argc, char **argv) {
|
||||
printf("%d\n", fib(atoi(argv[1])));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
fib (rec-lambda fib (n) (cond (= 0 n) 1
|
||||
(= 1 n) 1
|
||||
true (+ (fib (- n 1)) (fib (- n 2)))))
|
||||
|
||||
monad (array 'write 1 "enter number to fact: " (vau (written code)
|
||||
(array 'read 0 60 (vau (data code)
|
||||
(array 'exit (fib (read-string data)))
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,9 +0,0 @@
|
||||
import sys
|
||||
def fib(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
elif n == 1:
|
||||
return 1
|
||||
else:
|
||||
return fib(n-1) + fib(n-2)
|
||||
print(fib(int(sys.argv[1])))
|
||||
@@ -1,4 +0,0 @@
|
||||
(pretty-print ((letrec ((fib (lambda (n) (cond ((equal? n 0) 1)
|
||||
((equal? n 1) 1)
|
||||
(#t (+ (fib (- n 1)) (fib (- n 2))))))))
|
||||
fib) (read (open-input-string (list-ref (command-line) 1)))))
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
fib (lambda (n) ((lambda (fib) (fib fib n)) (lambda (fib n) (cond (= 0 n) 1
|
||||
(= 1 n) 1
|
||||
true (+ (fib fib (- n 1)) (fib fib (- n 2)))))))
|
||||
|
||||
monad (array 'write 1 "enter number to fact: " (vau (written code)
|
||||
(array 'read 0 60 (vau (data code)
|
||||
(array 'exit (fib (read-string data)))
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
int fib(n) {
|
||||
if (n == 0) {
|
||||
return 1;
|
||||
} else if (n == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
int r1 = fib(n-1);
|
||||
int r2 = fib(n-2);
|
||||
return r1 + r2;
|
||||
}
|
||||
}
|
||||
int main(int argc, char **argv) {
|
||||
printf("%d\n", fib(atoi(argv[1])));
|
||||
return 0;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
fib (rec-lambda fib (n) (cond (= 0 n) 1
|
||||
(= 1 n) 1
|
||||
true (let (
|
||||
fib_minus_1 (fib (- n 1))
|
||||
fib_minus_2 (fib (- n 2))
|
||||
) (+ fib_minus_1 fib_minus_2))))
|
||||
|
||||
monad (array 'write 1 "enter number to fact: " (vau (written code)
|
||||
(array 'read 0 60 (vau (data code)
|
||||
(array 'exit (fib (read-string data)))
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,11 +0,0 @@
|
||||
import sys
|
||||
def fib(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
elif n == 1:
|
||||
return 1
|
||||
else:
|
||||
r1 = fib(n-1)
|
||||
r2 = fib(n-2)
|
||||
return r1 + r2
|
||||
print(fib(int(sys.argv[1])))
|
||||
@@ -1,7 +0,0 @@
|
||||
(pretty-print ((letrec ((fib (lambda (n) (cond ((equal? n 0) 1)
|
||||
((equal? n 1) 1)
|
||||
(#t (let (
|
||||
(r1 (fib (- n 1)))
|
||||
(r2 (fib (- n 2)))
|
||||
) (+ r1 r2)))))))
|
||||
fib) (read (open-input-string (list-ref (command-line) 1)))))
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
NUMBER=30
|
||||
#NUMBER=27
|
||||
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm fib.kp
|
||||
mv csc_out.wasm fib_compiled.wasm
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm fib_let.kp
|
||||
mv csc_out.wasm fib_compiled_let.wasm
|
||||
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm fib.kp no_compile
|
||||
mv csc_out.wasm fib_interpreted.wasm
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm fib_let.kp no_compile
|
||||
mv csc_out.wasm fib_interpreted_let.wasm
|
||||
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm fib2.kp
|
||||
mv csc_out.wasm fib_compiled_manual.wasm
|
||||
touch csc_out.wasm && rm csc_out.wasm && scheme --script ../partial_eval.scm builtin_fib.kp
|
||||
mv csc_out.wasm builtin_fib.wasm
|
||||
|
||||
pushd rust_fib
|
||||
cargo build --target=wasm32-wasi
|
||||
cargo build --release --target=wasm32-wasi
|
||||
cargo build
|
||||
cargo build --release
|
||||
popd
|
||||
|
||||
pushd clojure_fib
|
||||
lein uberjar
|
||||
popd
|
||||
|
||||
pushd clojure_hi
|
||||
lein uberjar
|
||||
popd
|
||||
|
||||
hyperfine --warmup 2 --export-markdown table.md \
|
||||
'echo '$NUMBER' | wasmtime ./fib_compiled.wasm' 'echo '$NUMBER' | wasmtime ./fib_compiled_let.wasm' \
|
||||
'echo '$NUMBER' | wasmtime ./builtin_fib.wasm' 'echo '$NUMBER' | wasmtime ./fib_compiled_manual.wasm' \
|
||||
"scheme --script ./fib.scm $NUMBER" "scheme --script ./fib_let.scm $NUMBER" \
|
||||
"python3 ./fib.py $NUMBER" "python3 ./fib_let.py $NUMBER" \
|
||||
'echo '$NUMBER' | wasmtime ./rust_fib/target/wasm32-wasi/debug/rust_let.wasm' 'echo '$NUMBER' | wasmtime ./rust_fib/target/wasm32-wasi/release/rust_let.wasm' \
|
||||
"echo $NUMBER | java -jar ./clojure_fib/target/uberjar/clojure_fib-0.1.0-SNAPSHOT-standalone.jar" "echo $NUMBER | java -jar ./clojure_hi/target/uberjar/clojure_hi-0.1.0-SNAPSHOT-standalone.jar" \
|
||||
'echo '$NUMBER' | wasmtime ./fib_interpreted.wasm' 'echo '$NUMBER' | wasmtime ./fib_interpreted_let.wasm' \
|
||||
#end
|
||||
7
fib_test/rust_fib/Cargo.lock
generated
@@ -1,7 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "rust_let"
|
||||
version = "0.1.0"
|
||||
@@ -1,8 +0,0 @@
|
||||
[package]
|
||||
name = "rust_let"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
use std::io;
|
||||
|
||||
fn fib(n: i64) -> i64 {
|
||||
match n {
|
||||
0 => 1,
|
||||
1 => 1,
|
||||
o => fib(o-1) + fib(o-2),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("enter number to fib:");
|
||||
let mut buffer = String::new();
|
||||
let stdin = io::stdin();
|
||||
stdin.read_line(&mut buffer).unwrap();
|
||||
println!("{}", fib(buffer.trim().parse::<i64>().unwrap()));
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|
||||
|:---|---:|---:|---:|---:|
|
||||
| `echo 30 \| wasmtime ./fib_compiled.wasm` | 93.1 ± 0.7 | 91.6 | 94.7 | 7.28 ± 0.34 |
|
||||
| `echo 30 \| wasmtime ./fib_compiled_let.wasm` | 119.1 ± 0.7 | 118.2 | 120.4 | 9.31 ± 0.43 |
|
||||
| `echo 30 \| wasmtime ./builtin_fib.wasm` | 12.8 ± 0.6 | 11.4 | 14.7 | 1.00 |
|
||||
| `echo 30 \| wasmtime ./fib_compiled_manual.wasm` | 257.4 ± 5.8 | 245.4 | 262.8 | 20.12 ± 1.03 |
|
||||
| `scheme --script ./fib.scm 30` | 54.7 ± 1.2 | 52.7 | 57.9 | 4.27 ± 0.22 |
|
||||
| `scheme --script ./fib_let.scm 30` | 54.5 ± 0.9 | 52.7 | 56.1 | 4.26 ± 0.21 |
|
||||
| `python3 ./fib.py 30` | 283.5 ± 4.1 | 280.7 | 294.8 | 22.16 ± 1.07 |
|
||||
| `python3 ./fib_let.py 30` | 299.4 ± 2.1 | 296.9 | 304.7 | 23.41 ± 1.09 |
|
||||
| `echo 30 \| wasmtime ./rust_fib/target/wasm32-wasi/debug/rust_let.wasm` | 29.6 ± 0.6 | 28.5 | 31.4 | 2.31 ± 0.12 |
|
||||
| `echo 30 \| wasmtime ./rust_fib/target/wasm32-wasi/release/rust_let.wasm` | 18.7 ± 0.6 | 17.2 | 20.2 | 1.47 ± 0.08 |
|
||||
| `echo 30 \| java -jar ./clojure_fib/target/uberjar/clojure_fib-0.1.0-SNAPSHOT-standalone.jar` | 572.6 ± 17.4 | 546.0 | 599.5 | 44.76 ± 2.47 |
|
||||
| `echo 30 \| java -jar ./clojure_hi/target/uberjar/clojure_hi-0.1.0-SNAPSHOT-standalone.jar` | 555.2 ± 12.0 | 536.6 | 571.4 | 43.40 ± 2.21 |
|
||||
| `echo 30 \| wasmtime ./fib_interpreted.wasm` | 7716.7 ± 27.4 | 7679.8 | 7761.5 | 603.19 ± 27.93 |
|
||||
| `echo 30 \| wasmtime ./fib_interpreted_let.wasm` | 21414.3 ± 307.9 | 21122.2 | 22246.7 | 1673.87 ± 80.94 |
|
||||
98
flake.lock
generated
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1676283394,
|
||||
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -16,12 +19,15 @@
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"lastModified": 1681202837,
|
||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -36,11 +42,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1678760344,
|
||||
"narHash": "sha256-N8u9/O0NWt3PUQc9xmCeod1SFilOFicALjtYtslib2g=",
|
||||
"lastModified": 1700360261,
|
||||
"narHash": "sha256-8fRSHx5osjDELHSL7OHEfj/cOh8q+B7M9EF/yPR3bw8=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "d907affef544f64bd6886fe6bcc5fa2495a82373",
|
||||
"rev": "45066cb0b2505d8da581be8432a16238c867f199",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -51,11 +57,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1665296151,
|
||||
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
|
||||
"lastModified": 1681358109,
|
||||
"narHash": "sha256-eKyxW4OohHQx9Urxi7TQlFBTDWII+F+x2hklDOQPB50=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
|
||||
"rev": "96ba1c52e54e74c3197f4d43026b3f3d92e83ff9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -65,43 +71,13 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_stable_new": {
|
||||
"locked": {
|
||||
"lastModified": 1678703398,
|
||||
"narHash": "sha256-Y1mW3dBsoWLHpYm+UIHb5VZ7rx024NNHaF16oZBx++o=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "67f26c1cfc5d5783628231e776a81c1ade623e0b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-22.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs_stable_old": {
|
||||
"locked": {
|
||||
"lastModified": 1659446231,
|
||||
"narHash": "sha256-hekabNdTdgR/iLsgce5TGWmfIDZ86qjPhxDg/8TlzhE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "eabc38219184cc3e04a974fe31857d8e0eac098d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-21.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs_unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1678838343,
|
||||
"narHash": "sha256-aA48yVAUyppdlVHhMStlWjB8u9uzA5iel3C47xlbkrw=",
|
||||
"lastModified": 1700412808,
|
||||
"narHash": "sha256-1yU5WT0sfRJ2DOVZ+6oDdpUZ6j0hz0JBPpbqj8/VCJQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b16f2a75619fe8e6adf4583f5fc6448bc967d482",
|
||||
"rev": "38b1656c2d775b6abc6d08cfc8f38b8847a73ec4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -114,10 +90,38 @@
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"moz_overlay": "moz_overlay",
|
||||
"nixpkgs_stable_new": "nixpkgs_stable_new",
|
||||
"nixpkgs_stable_old": "nixpkgs_stable_old",
|
||||
"nixpkgs_unstable": "nixpkgs_unstable"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
21
flake.nix
@@ -2,23 +2,25 @@
|
||||
description = "Env for Kraken and the extacted Koka bencmarks";
|
||||
inputs = {
|
||||
# For some reason the newer one has broken koka/emscripten (probs same change)
|
||||
nixpkgs_stable_new.url = "nixpkgs/nixos-22.11";
|
||||
nixpkgs_stable_old.url = "nixpkgs/nixos-21.11";
|
||||
#nixpkgs_stable_new.url = "nixpkgs/nixos-22.11";
|
||||
#nixpkgs_stable_old.url = "nixpkgs/nixos-21.11";
|
||||
nixpkgs_unstable.url = "github:NixOS/nixpkgs";
|
||||
moz_overlay.url = "github:oxalica/rust-overlay";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
outputs = { self, nixpkgs_stable_new, nixpkgs_stable_old, nixpkgs_unstable, moz_overlay, flake-utils }:
|
||||
outputs = { self,
|
||||
#nixpkgs_stable_new, nixpkgs_stable_old,
|
||||
nixpkgs_unstable, moz_overlay, flake-utils }:
|
||||
(flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs_new = import nixpkgs_unstable {
|
||||
inherit system;
|
||||
overlays = [ moz_overlay.overlay ];
|
||||
};
|
||||
pkgs_old = import nixpkgs_stable_old {
|
||||
inherit system;
|
||||
overlays = [ moz_overlay.overlay ];
|
||||
};
|
||||
#pkgs_old = import nixpkgs_stable_old {
|
||||
# inherit system;
|
||||
# overlays = [ moz_overlay.overlay ];
|
||||
#};
|
||||
#newlisp = pkgs.stdenv.mkDerivation rec {
|
||||
#pname = "newLisp";
|
||||
#version = "10.7.5";
|
||||
@@ -98,10 +100,11 @@
|
||||
#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
|
||||
#pkgs_old.emscripten
|
||||
|
||||
#picolisp
|
||||
#newlisp
|
||||
|
||||
559
kr/Cargo.lock
generated
@@ -1,559 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
|
||||
dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kr"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"atty",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"ena",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"pico-args",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"string_cache",
|
||||
"term",
|
||||
"tiny-keccak",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468"
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
338
kr/src/ast.rs
@@ -1,338 +0,0 @@
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use std::convert::From;
|
||||
|
||||
// TODO:
|
||||
// -extend vau & env logic and SuspendedPair PE with sequence_params & wrap_level
|
||||
// -add current-hashes to if
|
||||
// -expand combiner_Return_ok with (func ...params) | func doesn't take de and func+params are return ok
|
||||
// -add recursive drop redundent veval
|
||||
// -mark rec-hash on DeriComb
|
||||
// -add compiler
|
||||
//
|
||||
// -use current fake comb ids instead of hashes
|
||||
// -do they have to be added to not-under thing like hashes
|
||||
// -make cons work only for SuspendedParam/Env
|
||||
|
||||
impl From<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
|
||||
impl From<bool> for Form { fn from(item: bool) -> Self { Form::Bool(item) } }
|
||||
// todo, strings not symbols?
|
||||
impl From<String> for Form { fn from(item: String) -> Self { Form::Symbol(item) } }
|
||||
impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned()) } }
|
||||
|
||||
impl<A: Into<Form>, B: Into<Form>> From<(A, B)> for Form {
|
||||
fn from(item: (A, B)) -> Self {
|
||||
Form::Pair(Rc::new(item.0.into()), Rc::new(item.1.into()))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PossibleTailCall {
|
||||
Result(Rc<Form>),
|
||||
TailCall(Rc<Form>, Rc<Form>),
|
||||
}
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Form {
|
||||
Nil,
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
Symbol(String),
|
||||
Pair(Rc<Form>,Rc<Form>),
|
||||
PrimComb(String, fn(Rc<Form>, Rc<Form>) -> PossibleTailCall),
|
||||
DeriComb { se: Rc<Form>, de: Option<String>, params: String, body: Rc<Form> },
|
||||
}
|
||||
impl Form {
|
||||
pub fn truthy(&self) -> bool {
|
||||
match self {
|
||||
Form::Bool(b) => *b,
|
||||
Form::Nil => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
pub fn int(&self) -> Option<i32> {
|
||||
match self {
|
||||
Form::Int(i) => Some(*i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn sym(&self) -> Option<&str> {
|
||||
match self {
|
||||
Form::Symbol(s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn car(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, _cdr) => Some(Rc::clone(car)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn cdr(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(_car, cdr) => Some(Rc::clone(cdr)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn append(&self, x: Rc<Form>) -> Option<Form> {
|
||||
match self {
|
||||
Form::Pair(car, cdr) => cdr.append(x).map(|x| Form::Pair(Rc::clone(car), Rc::new(x))),
|
||||
Form::Nil => Some(Form::Pair(x, Rc::new(Form::Nil))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Form {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Form::Nil => write!(f, "nil"),
|
||||
Form::Int(i) => write!(f, "{}", i),
|
||||
Form::Bool(b) => write!(f, "{}", b),
|
||||
Form::Symbol(s) => write!(f, "{}", s),
|
||||
Form::Pair(car, cdr) => {
|
||||
write!(f, "({}", car)?;
|
||||
let mut traverse: Rc<Form> = Rc::clone(cdr);
|
||||
loop {
|
||||
match &*traverse {
|
||||
Form::Pair(ref carp, ref cdrp) => {
|
||||
write!(f, " {}", carp)?;
|
||||
traverse = Rc::clone(cdrp);
|
||||
},
|
||||
Form::Nil => {
|
||||
write!(f, ")")?;
|
||||
return Ok(());
|
||||
},
|
||||
x => {
|
||||
write!(f, ". {})", x)?;
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Form::PrimComb(name, _f) => write!(f, "<{}>", name),
|
||||
Form::DeriComb { se, de, params, body } => {
|
||||
write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(e: Rc<Form>, f: Rc<Form>) -> Rc<Form> {
|
||||
let mut e = e;
|
||||
let mut x = Option::Some(f);
|
||||
loop {
|
||||
let cur = x.take().unwrap();
|
||||
//println!("Evaluating {:?} in {:?}", cur, e);
|
||||
match *cur {
|
||||
Form::Symbol(ref s) => {
|
||||
let mut t = e;
|
||||
//println!("Looking up {} in {:?}", s, t);
|
||||
//println!("Looking up {}", s);
|
||||
while s != t.car().unwrap().car().unwrap().sym().unwrap() {
|
||||
t = t.cdr().unwrap();
|
||||
}
|
||||
return t.car().unwrap().cdr().unwrap();
|
||||
},
|
||||
Form::Pair(ref c, ref p) => {
|
||||
let comb = eval(Rc::clone(&e), Rc::clone(c));
|
||||
match *comb {
|
||||
Form::PrimComb(ref _n, ref f) => match f(e, Rc::clone(p)) {
|
||||
PossibleTailCall::Result(r) => return r,
|
||||
PossibleTailCall::TailCall(ne, nx) => {
|
||||
e = ne;
|
||||
x = Some(nx);
|
||||
},
|
||||
},
|
||||
Form::DeriComb{ref se, ref de, ref params, ref body } => {
|
||||
let mut new_e = Rc::clone(se);
|
||||
if let Some(de) = de {
|
||||
new_e = assoc(de, Rc::clone(&e), new_e);
|
||||
}
|
||||
new_e = assoc(params, Rc::clone(p), new_e);
|
||||
// always a tail call
|
||||
e = new_e;
|
||||
x = Some(Rc::clone(body));
|
||||
},
|
||||
_ => panic!("Tried to call not a Prim/DeriComb {:?}", comb),
|
||||
}
|
||||
},
|
||||
_ => return cur,
|
||||
}
|
||||
}
|
||||
}
|
||||
fn assoc(k: &str, v: Rc<Form>, l: Rc<Form>) -> Rc<Form> {
|
||||
Rc::new(Form::Pair(
|
||||
Rc::new(Form::Pair(
|
||||
Rc::new(Form::Symbol(k.to_owned())),
|
||||
v)),
|
||||
l))
|
||||
}
|
||||
fn assoc_vec(kvs: Vec<(&str, Rc<Form>)>) -> Rc<Form> {
|
||||
let mut to_ret = Rc::new(Form::Nil);
|
||||
for (k, v) in kvs {
|
||||
to_ret = assoc(k, v, to_ret);
|
||||
}
|
||||
to_ret
|
||||
}
|
||||
|
||||
pub fn root_env() -> Rc<Form> {
|
||||
assoc_vec(vec![
|
||||
("eval", Rc::new(Form::PrimComb("eval".to_owned(), |e, p| {
|
||||
let b = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let e = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::TailCall(e, b)
|
||||
}))),
|
||||
// (vau de params body)
|
||||
("vau", Rc::new(Form::PrimComb("vau".to_owned(), |e, p| {
|
||||
let de = p.car().unwrap().sym().map(|s| s.to_owned());
|
||||
let params = p.cdr().unwrap().car().unwrap().sym().unwrap().to_owned();
|
||||
let body = p.cdr().unwrap().cdr().unwrap().car().unwrap();
|
||||
|
||||
PossibleTailCall::Result(Rc::new(Form::DeriComb { se: e, de, params, body }))
|
||||
}))),
|
||||
("=", Rc::new(Form::PrimComb("=".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(a == b)))
|
||||
}))),
|
||||
("<", Rc::new(Form::PrimComb("<".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() < b.int().unwrap())))
|
||||
}))),
|
||||
(">", Rc::new(Form::PrimComb(">".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() > b.int().unwrap())))
|
||||
}))),
|
||||
("<=", Rc::new(Form::PrimComb("<=".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() <= b.int().unwrap())))
|
||||
}))),
|
||||
(">=", Rc::new(Form::PrimComb(">=".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() >= b.int().unwrap())))
|
||||
}))),
|
||||
("if", Rc::new(Form::PrimComb("if".to_owned(), |e, p| {
|
||||
if eval(Rc::clone(&e), p.car().unwrap()).truthy() {
|
||||
PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap())
|
||||
} else {
|
||||
PossibleTailCall::TailCall(e, p.cdr().unwrap().cdr().unwrap().car().unwrap())
|
||||
}
|
||||
}))),
|
||||
("cons", Rc::new(Form::PrimComb("cons".to_owned(), |e, p| {
|
||||
let h = eval(Rc::clone(&e), p.car().unwrap());
|
||||
let t = eval(e, p.cdr().unwrap().car().unwrap());
|
||||
PossibleTailCall::Result(Rc::new(Form::Pair(h, t)))
|
||||
}))),
|
||||
("car", Rc::new(Form::PrimComb("car".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).car().unwrap())
|
||||
}))),
|
||||
("cdr", Rc::new(Form::PrimComb("cdr".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).cdr().unwrap())
|
||||
}))),
|
||||
("quote", Rc::new(Form::PrimComb("quote".to_owned(), |_e, p| {
|
||||
PossibleTailCall::Result(p.car().unwrap())
|
||||
}))),
|
||||
|
||||
("debug", Rc::new(Form::PrimComb("debug".to_owned(), |e, p| {
|
||||
//println!("Debug: {:?}", eval(Rc::clone(&e), p.car().unwrap()));
|
||||
println!("Debug: {}", eval(Rc::clone(&e), p.car().unwrap()));
|
||||
PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap())
|
||||
}))),
|
||||
("assert", Rc::new(Form::PrimComb("assert".to_owned(), |e, p| {
|
||||
let thing = eval(Rc::clone(&e), p.car().unwrap());
|
||||
if !thing.truthy() {
|
||||
println!("Assert failed: {:?}", thing);
|
||||
}
|
||||
assert!(thing.truthy());
|
||||
PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap())
|
||||
}))),
|
||||
|
||||
("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a + b)))
|
||||
}))),
|
||||
("-", Rc::new(Form::PrimComb("-".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a - b)))
|
||||
}))),
|
||||
("*", Rc::new(Form::PrimComb("*".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a * b)))
|
||||
}))),
|
||||
("/", Rc::new(Form::PrimComb("/".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a / b)))
|
||||
}))),
|
||||
("%", Rc::new(Form::PrimComb("%".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a % b)))
|
||||
}))),
|
||||
("&", Rc::new(Form::PrimComb("&".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a & b)))
|
||||
}))),
|
||||
("|", Rc::new(Form::PrimComb("|".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a | b)))
|
||||
}))),
|
||||
("^", Rc::new(Form::PrimComb("^".to_owned(), |e, p| {
|
||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
||||
let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap();
|
||||
PossibleTailCall::Result(Rc::new(Form::Int(a ^ b)))
|
||||
}))),
|
||||
|
||||
("comb?", Rc::new(Form::PrimComb("comb?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::PrimComb(_n, _f) => true,
|
||||
Form::DeriComb { .. } => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
("pair?", Rc::new(Form::PrimComb("pair?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::Pair(_a,_b) => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
("symbol?", Rc::new(Form::PrimComb("symbol?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::Symbol(_) => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
("int?", Rc::new(Form::PrimComb("int?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::Int(_) => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
// maybe bool? but also could be derived. Nil def
|
||||
("bool?", Rc::new(Form::PrimComb("bool?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::Bool(_) => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
("nil?", Rc::new(Form::PrimComb("nil?".to_owned(), |e, p| {
|
||||
PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) {
|
||||
Form::Nil => true,
|
||||
_ => false,
|
||||
})))
|
||||
}))),
|
||||
|
||||
// consts
|
||||
("true", Rc::new(Form::Bool(true))),
|
||||
("false", Rc::new(Form::Bool(false))),
|
||||
("nil", Rc::new(Form::Nil)),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
use std::str::FromStr;
|
||||
use std::rc::Rc;
|
||||
use crate::ast::Form;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Term: Form = {
|
||||
NUM => Form::Int(i32::from_str(<>).unwrap()),
|
||||
SYM => Form::Symbol(<>.to_owned()),
|
||||
"(" <ListInside?> ")" => <>.unwrap_or(Form::Nil),
|
||||
"'" <Term> => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(Form::Pair(Rc::new(<>), Rc::new(Form::Nil)))),
|
||||
"!" <h: Term> <t: Term> => {
|
||||
h.append(Rc::new(t)).unwrap()
|
||||
},
|
||||
};
|
||||
ListInside: Form = {
|
||||
<Term> => Form::Pair(Rc::new(<>), Rc::new(Form::Nil)),
|
||||
<h: Term> <t: ListInside> => Form::Pair(Rc::new(h), Rc::new(t)),
|
||||
<a: Term> "." <d: Term> => Form::Pair(Rc::new(a), Rc::new(d)),
|
||||
}
|
||||
match {
|
||||
"(",
|
||||
")",
|
||||
".",
|
||||
"'",
|
||||
"!",
|
||||
r"[0-9]+" => NUM,
|
||||
r"[a-zA-Z+*/_=?%&|^<>-][\w+*/=_?%&|^<>-]*" => SYM,
|
||||
r"(;[^\n]*\n)|\s+" => { }
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#[macro_use] extern crate lalrpop_util;
|
||||
lalrpop_mod!(pub grammar);
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
mod ast;
|
||||
use crate::ast::{eval,root_env};
|
||||
mod pe_ast;
|
||||
use crate::pe_ast::{mark,partial_eval,new_base_ctxs};
|
||||
|
||||
mod test;
|
||||
|
||||
|
||||
fn main() {
|
||||
let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))";
|
||||
let parsed_input = Rc::new(grammar::TermParser::new().parse(input).unwrap());
|
||||
println!("Parsed input is {} - {:?}", parsed_input, parsed_input);
|
||||
let (bctx, dctx) = new_base_ctxs();
|
||||
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 result = eval(root_env(), parsed_input);
|
||||
println!("Result is {} - {:?}", result, result);
|
||||
}
|
||||
|
||||
1042
kr/src/pe_ast.rs
0
kr/.gitignore → kv/.gitignore
vendored
967
kv/Cargo.lock
generated
Normal file
@@ -0,0 +1,967 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
|
||||
dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50babaf4da30fd349e1b913760300266143535f15a0b7be7ce1ce9efafa8ff5e"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-frontend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1277fbfa94bc82c8ec4af2ded3e639d49ca5f7f3c7eeab2c66accd135ece4e70"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6e8c31ad3b2270e9aeec38723888fe1b0ace3bea2b06b3f749ccf46661d3220"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity",
|
||||
"cranelift-isle",
|
||||
"gimli",
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
"regalloc2",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8ac5ac30d62b2d66f12651f6b606dbdfd9c2cfd0908de6b387560a277c5c9da"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd82b8b376247834b59ed9bdc0ddeb50f517452827d4a11bccf5937b213748b8"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40099d38061b37e505e63f89bab52199037a72b931ad4868d9089ff7268660b0"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a25d9d0a0ae3079c463c34115ec59507b4707175454f0eee0891e83e30e82d"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80de6a7d0486e4acbd5f9f87ec49912bf4c8fb6aea00087b989685460d4469ba"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ca96b05988aa057eda09a817a6e31915fabd7f476b513123aff08053cd193dd"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"libc",
|
||||
"log",
|
||||
"region",
|
||||
"target-lexicon",
|
||||
"wasmtime-jit-icache-coherence",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5112c0be9cc5da064e0620570d67852f11ce44f2e572a58ecf7f11df73978b8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.95.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb6b03e0e03801c4b3fd8ce0758a94750c07a44e7944cc0ffbf0d3f2e7c79b00"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap 1.9.3",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kv"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift",
|
||||
"cranelift-jit",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"ena",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"regex",
|
||||
"regex-syntax 0.6.29",
|
||||
"string_cache",
|
||||
"term",
|
||||
"tiny-keccak",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap 2.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80535183cae11b149d618fbd3c37e38d7cda589d82d7769e196ca9a9042d7621"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"log",
|
||||
"slice-group-by",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "region"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
"mach",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "slice-group-by"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "8.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aecae978b13f7f67efb23bd827373ace4578f2137ec110bbf6a4a7cde4121bbd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
@@ -1,16 +1,24 @@
|
||||
[package]
|
||||
name = "kr"
|
||||
name = "kv"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
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"
|
||||
once_cell = "1.17.0"
|
||||
anyhow = "1"
|
||||
cranelift = "0.95.1"
|
||||
cranelift-module = "0.95.1"
|
||||
cranelift-jit = "0.95.1"
|
||||
cranelift-native = "0.95.1"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19.7"
|
||||
308
kv/src/basic.rs
Normal file
@@ -0,0 +1,308 @@
|
||||
use std::fmt;
|
||||
use std::boxed::Box;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
|
||||
use crate::eval::{FormT,Cont,Cursor,PrimCombI};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Form {
|
||||
Nil,
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
Symbol(String),
|
||||
Cell(RefCell<Rc<Form>>),
|
||||
Pair(Rc<Form>,Rc<Form>),
|
||||
PrimComb { eval_limit: i32, ins: PrimCombI },
|
||||
DeriComb { se: Rc<Form>, de: Option<String>, params: String, body: Rc<Form> },
|
||||
ContComb(Cont<Form>),
|
||||
}
|
||||
|
||||
// todo, strings not symbols?
|
||||
impl From<String> for Form { fn from(item: String) -> Self { Form::Symbol(item) } }
|
||||
impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned()) } }
|
||||
impl From<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
|
||||
impl From<bool> for Form { fn from(item: bool) -> Self { Form::Bool(item) } }
|
||||
impl<A: Into<Form>, B: Into<Form>> From<(A, B)> for Form {
|
||||
fn from(item: (A, B)) -> Self {
|
||||
Form::Pair(Rc::new(item.0.into()), Rc::new(item.1.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Form {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Form::Nil => write!(f, "nil"),
|
||||
Form::Int(i) => write!(f, "{i}"),
|
||||
Form::Bool(b) => write!(f, "{b}"),
|
||||
Form::Symbol(s) => write!(f, "{s}"),
|
||||
Form::Cell(c) => write!(f, "@{}", c.borrow()),
|
||||
Form::Pair(car, cdr) => {
|
||||
write!(f, "({}", car)?;
|
||||
let mut traverse: Rc<Form> = Rc::clone(cdr);
|
||||
loop {
|
||||
match &*traverse {
|
||||
Form::Pair(ref carp, ref cdrp) => {
|
||||
write!(f, " {}", carp)?;
|
||||
traverse = Rc::clone(cdrp);
|
||||
},
|
||||
Form::Nil => {
|
||||
write!(f, ")")?;
|
||||
return Ok(());
|
||||
},
|
||||
x => {
|
||||
write!(f, ". {x})")?;
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Form::PrimComb { eval_limit, ins } => write!(f, "<{eval_limit}> - {ins:?}"),
|
||||
Form::DeriComb { se: _, de, params, body } => {
|
||||
write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body)
|
||||
},
|
||||
Form::ContComb(_) => write!(f, "<cont>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Form {
|
||||
fn truthy(&self) -> bool {
|
||||
match self {
|
||||
Form::Bool(b) => *b,
|
||||
Form::Nil => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
fn int(&self) -> Option<i32> {
|
||||
match self {
|
||||
Form::Int(i) => Some(*i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn append(&self, x: Rc<Form>) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, cdr) => cdr.append(x).map(|x| Rc::new(Form::Pair(Rc::clone(car), x))),
|
||||
Form::Nil => Some(Rc::new(Form::Pair(x, Rc::new(Form::Nil)))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormT for Form {
|
||||
fn sym(&self) -> Option<&str> {
|
||||
match self {
|
||||
Form::Symbol(s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn pair(&self) -> Option<(Rc<Form>,Rc<Form>)> {
|
||||
match self {
|
||||
Form::Pair(car, cdr) => Some((Rc::clone(car),Rc::clone(cdr))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn car(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, _cdr) => Some(Rc::clone(car)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn cdr(&self) -> Option<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(_car, cdr) => Some(Rc::clone(cdr)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn is_nil(&self) -> bool {
|
||||
match self {
|
||||
Form::Nil => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn call(&self, p: Rc<Self>, e: Rc<Self>, nc: Box<Cont<Self>>, metac: Cont<Self>) -> Cursor<Self> {
|
||||
match self {
|
||||
Form::PrimComb{eval_limit, ins} => {
|
||||
Cursor { f: Rc::new(Form::Nil), c: Cont::PramEval { eval_limit: *eval_limit, to_eval: p, collected: None, e, ins: *ins, nc: nc }, metac }
|
||||
}
|
||||
Form::DeriComb {se, de, params, body} => {
|
||||
let mut new_e = Rc::clone(se);
|
||||
if let Some(de) = de {
|
||||
new_e = assoc(&de, Rc::clone(&e), new_e);
|
||||
}
|
||||
new_e = assoc(¶ms, p, new_e);
|
||||
Cursor { f: Rc::clone(body), c: Cont::Eval { e: new_e, nc: nc }, metac }
|
||||
}
|
||||
Form::ContComb(c) => {
|
||||
Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } }
|
||||
}
|
||||
_ => {
|
||||
panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", self, nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn impl_prim(ins: PrimCombI, e: Rc<Self>, ps: Vec<Rc<Self>>, c: Cont<Self>, metac: Cont<Self>) -> Cursor<Self> {
|
||||
match ins {
|
||||
PrimCombI::Eval => Cursor { f: Rc::clone(&ps[0]), c: Cont::Eval { e: Rc::clone(&ps[1]), nc: Box::new(c) }, metac },
|
||||
PrimCombI::Vau => {
|
||||
let de = ps[0].sym().map(|s| s.to_owned());
|
||||
let params = ps[1].sym().unwrap().to_owned();
|
||||
let body = Rc::clone(&ps[2]);
|
||||
|
||||
Cursor { f: Rc::new(Form::DeriComb { se: e, de, params, body }), c, metac }
|
||||
},
|
||||
PrimCombI::If => if ps[0].truthy() {
|
||||
Cursor { f: Rc::clone(&ps[1]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
} else {
|
||||
Cursor { f: Rc::clone(&ps[2]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
},
|
||||
|
||||
PrimCombI::Reset => Cursor { f: Rc::clone(&ps[0]),
|
||||
c: Cont::Eval { e: e, nc: Box::new(Cont::MetaRet) },
|
||||
metac: Cont::CatchRet { nc: Box::new(c), restore_meta: Box::new(metac) } },
|
||||
PrimCombI::Shift => Cursor { f: Rc::clone(&ps[0]),
|
||||
c: Cont::Call { p: Rc::new(Form::Pair(Rc::new(Form::ContComb(c)),
|
||||
Rc::new(Form::Nil))),
|
||||
e: e,
|
||||
nc: Box::new(Cont::MetaRet) },
|
||||
// I think this is unnecessary and can just be "metac },"
|
||||
// because reset puts this metac in
|
||||
metac: Cont::CatchRet { nc: Box::new(metac.clone()), restore_meta: Box::new(metac) } },
|
||||
PrimCombI::Assert => {
|
||||
let thing = Rc::clone(&ps[0]);
|
||||
if !thing.truthy() {
|
||||
println!("Assert failed: {:?}", thing);
|
||||
}
|
||||
assert!(thing.truthy());
|
||||
Cursor { f: Rc::clone(&ps[1]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
},
|
||||
|
||||
PrimCombI::Cell => Cursor { f: Rc::new(Form::Cell(RefCell::new(Rc::clone(&ps[0])))), c, metac },
|
||||
PrimCombI::Set => match &*ps[0] {
|
||||
Form::Cell(cell) => Cursor { f: cell.replace(Rc::clone(&ps[1])), c, metac },
|
||||
_ => panic!("set on not cell"),
|
||||
},
|
||||
PrimCombI::Get => match &*ps[0] {
|
||||
Form::Cell(cell) => Cursor { f: Rc::clone(&cell.borrow()), c, metac },
|
||||
_ => panic!("get on not cell"),
|
||||
},
|
||||
|
||||
PrimCombI::Cons => Cursor { f: Rc::new(Form::Pair(Rc::clone(&ps[0]), Rc::clone(&ps[1]))), c, metac },
|
||||
PrimCombI::Car => Cursor { f: ps[0].car().unwrap(), c, metac },
|
||||
PrimCombI::Cdr => Cursor { f: ps[0].cdr().unwrap(), c, metac },
|
||||
PrimCombI::Quote => Cursor { f: Rc::clone(&ps[0]), c, metac },
|
||||
|
||||
PrimCombI::Eq => Cursor { f: Rc::new(Form::Bool(ps[0] == ps[1])), c, metac },
|
||||
PrimCombI::Lt => Cursor { f: Rc::new(Form::Bool(ps[0].int().unwrap() < ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::LEq => Cursor { f: Rc::new(Form::Bool(ps[0].int().unwrap() <= ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Gt => Cursor { f: Rc::new(Form::Bool(ps[0].int().unwrap() > ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::GEq => Cursor { f: Rc::new(Form::Bool(ps[0].int().unwrap() >= ps[1].int().unwrap())), c, metac },
|
||||
|
||||
PrimCombI::Plus => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() + ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Minus => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() - ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Mult => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() * ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Div => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() / ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Mod => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() % ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::And => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() & ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Or => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() | ps[1].int().unwrap())), c, metac },
|
||||
PrimCombI::Xor => Cursor { f: Rc::new(Form::Int(ps[0].int().unwrap() ^ ps[1].int().unwrap())), c, metac },
|
||||
|
||||
PrimCombI::CombP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::PrimComb { .. } => true,
|
||||
Form::DeriComb { .. } => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::CellP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::Cell(_c) => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::PairP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::Pair(_a,_b) => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::SymbolP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::Symbol(_) => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::IntP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::Int(_) => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::BoolP => Cursor { f: Rc::new(Form::Bool(match &*ps[0] {
|
||||
Form::Bool(_) => true,
|
||||
_ => false,
|
||||
})), c, metac },
|
||||
PrimCombI::NilP => Cursor { f: Rc::new(Form::Bool(ps[0].is_nil())), c, metac },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assoc(k: &str, v: Rc<Form>, l: Rc<Form>) -> Rc<Form> {
|
||||
Rc::new(Form::Pair(
|
||||
Rc::new(Form::Pair(
|
||||
Rc::new(Form::Symbol(k.to_owned())),
|
||||
v)),
|
||||
l))
|
||||
}
|
||||
pub fn assoc_vec(kvs: Vec<(&str, Rc<Form>)>) -> Rc<Form> {
|
||||
let mut to_ret = Rc::new(Form::Nil);
|
||||
for (k, v) in kvs {
|
||||
to_ret = assoc(k, v, to_ret);
|
||||
}
|
||||
to_ret
|
||||
}
|
||||
|
||||
// Have eval?/maybe Cont?/maybe Cursor? parameterized on value type?
|
||||
// Parameterized on prim implementation?
|
||||
// Should opt impl use same prim implementation but trace values through accessors/constructors?
|
||||
// with some special handling of If/Vau/etc?
|
||||
|
||||
pub fn root_env() -> Rc<Form> {
|
||||
assoc_vec(vec![
|
||||
("eval", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Eval })),
|
||||
("vau", Rc::new(Form::PrimComb { eval_limit: 0, ins: PrimCombI::Vau })),
|
||||
("if", Rc::new(Form::PrimComb { eval_limit: 1, ins: PrimCombI::If })),
|
||||
|
||||
("reset", Rc::new(Form::PrimComb { eval_limit: 0, ins: PrimCombI::Reset })),
|
||||
("shift", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Shift })),
|
||||
|
||||
("cell", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Cell })),
|
||||
("set", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Set })),
|
||||
("get", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Get })),
|
||||
|
||||
("cons", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Cons })),
|
||||
("car", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Car })),
|
||||
("cdr", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Cdr })),
|
||||
("quote", Rc::new(Form::PrimComb { eval_limit: 0, ins: PrimCombI::Quote })),
|
||||
("assert", Rc::new(Form::PrimComb { eval_limit: 1, ins: PrimCombI::Assert })),
|
||||
|
||||
("=", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Eq })),
|
||||
("<", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Lt })),
|
||||
("<=", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::LEq })),
|
||||
(">", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Gt })),
|
||||
(">=", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::GEq })),
|
||||
|
||||
("+", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Plus })),
|
||||
("-", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Minus })),
|
||||
("*", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Mult })),
|
||||
("/", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Div })),
|
||||
("%", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Mod })),
|
||||
("&", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::And })),
|
||||
("|", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Or })),
|
||||
("^", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::Xor })),
|
||||
|
||||
("comb?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::CombP })),
|
||||
("cell?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::CellP })),
|
||||
("pair?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::PairP })),
|
||||
("symbol?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::SymbolP })),
|
||||
("int?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::IntP })),
|
||||
("bool?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::BoolP })),
|
||||
("nil?", Rc::new(Form::PrimComb { eval_limit: -1, ins: PrimCombI::NilP })),
|
||||
|
||||
("true", Rc::new(Form::Bool(true))),
|
||||
("false", Rc::new(Form::Bool(false))),
|
||||
("nil", Rc::new(Form::Nil)),
|
||||
])
|
||||
}
|
||||
|
||||
136
kv/src/eval.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
use std::fmt;
|
||||
use std::boxed::Box;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
|
||||
pub trait FormT: std::fmt::Debug {
|
||||
fn sym(&self) -> Option<&str>;
|
||||
fn pair(&self) -> Option<(Rc<Self>,Rc<Self>)>;
|
||||
fn car(&self) -> Option<Rc<Self>>;
|
||||
fn cdr(&self) -> Option<Rc<Self>>;
|
||||
fn is_nil(&self) -> bool;
|
||||
fn call(&self, p: Rc<Self>, e: Rc<Self>, nc: Box<Cont<Self>>, metac: Cont<Self>) -> Cursor<Self>;
|
||||
fn impl_prim(ins: PrimCombI, e: Rc<Self>, ps: Vec<Rc<Self>>, c: Cont<Self>, metac: Cont<Self>) -> Cursor<Self>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Cont<F: FormT + ?Sized> {
|
||||
Exit,
|
||||
MetaRet,
|
||||
CatchRet { nc: Box<Cont<F>>, restore_meta: Box<Cont<F>> },
|
||||
Eval { e: Rc<F>, nc: Box<Cont<F>> },
|
||||
Call { p: Rc<F>, e: Rc<F>, nc: Box<Cont<F>> },
|
||||
PramEval { eval_limit: i32, to_eval: Rc<F>, collected: Option<Vec<Rc<F>>>, e: Rc<F>, ins: PrimCombI, nc: Box<Cont<F>> },
|
||||
}
|
||||
impl<F: FormT> Clone for Cont<F> {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Cont::Exit => Cont::Exit,
|
||||
Cont::MetaRet => Cont::MetaRet,
|
||||
Cont::CatchRet { nc, restore_meta } => Cont::CatchRet { nc: nc.clone(), restore_meta: restore_meta.clone() },
|
||||
Cont::Eval { e, nc } => Cont::Eval { e: Rc::clone(e), nc: nc.clone() },
|
||||
Cont::Call { p, e, nc } => Cont::Call { p: Rc::clone(p), e: Rc::clone(e), nc: nc.clone() },
|
||||
Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc} => Cont::PramEval { eval_limit: *eval_limit, to_eval: Rc::clone(to_eval),
|
||||
collected: collected.as_ref().map(|x| x.iter().map(|x| Rc::clone(x)).collect()),
|
||||
e: Rc::clone(e), ins: ins.clone(), nc: nc.clone() },
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct Cursor<F: FormT + ?Sized> { pub f: Rc<F>, pub c: Cont<F>, pub metac: Cont<F> }
|
||||
|
||||
pub fn eval<F: FormT>(e: Rc<F>, f: Rc<F>) -> Rc<F> {
|
||||
let mut cursor = Cursor::<F> { f, c: Cont::Eval { e, nc: Box::new(Cont::MetaRet) }, metac: Cont::Exit };
|
||||
loop {
|
||||
let Cursor { f, c, metac } = cursor;
|
||||
match c {
|
||||
Cont::Exit => {
|
||||
return f;
|
||||
},
|
||||
Cont::MetaRet => {
|
||||
cursor = Cursor { f: f, c: metac.clone(), metac: metac };
|
||||
},
|
||||
Cont::CatchRet { nc, restore_meta } => {
|
||||
cursor = Cursor { f: f, c: *nc, metac: *restore_meta };
|
||||
},
|
||||
Cont::Eval { e, nc } => {
|
||||
if let Some((comb, p)) = f.pair() {
|
||||
cursor = Cursor { f: comb, c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::Call { p, e, nc }) }, metac }
|
||||
} else if let Some(s) = f.sym() {
|
||||
let mut t = Rc::clone(&e);
|
||||
while s != t.car().unwrap().car().unwrap().sym().unwrap() {
|
||||
t = t.cdr().unwrap();
|
||||
}
|
||||
cursor = Cursor { f: t.car().unwrap().cdr().unwrap(), c: *nc, metac };
|
||||
} else {
|
||||
cursor = Cursor { f: Rc::clone(&f), c: *nc, metac };
|
||||
}
|
||||
},
|
||||
Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc } => {
|
||||
let mut next_collected = if let Some(mut collected) = collected {
|
||||
collected.push(f); collected
|
||||
} else { vec![] };
|
||||
if eval_limit == 0 || to_eval.is_nil() {
|
||||
let mut traverse = to_eval;
|
||||
while !traverse.is_nil() {
|
||||
next_collected.push(traverse.car().unwrap());
|
||||
traverse = traverse.cdr().unwrap();
|
||||
}
|
||||
cursor = F::impl_prim(ins, e, next_collected, *nc, metac);
|
||||
} else {
|
||||
cursor = Cursor { f: to_eval.car().unwrap(), c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::PramEval { eval_limit: eval_limit - 1,
|
||||
to_eval: to_eval.cdr().unwrap(),
|
||||
collected: Some(next_collected),
|
||||
e, ins, nc }) }, metac };
|
||||
}
|
||||
},
|
||||
Cont::Call { p, e, nc } => {
|
||||
cursor = f.call(p, e, nc, metac);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum PrimCombI {
|
||||
Eval,
|
||||
Vau,
|
||||
If,
|
||||
|
||||
Reset,
|
||||
Shift,
|
||||
|
||||
Cell,
|
||||
Set,
|
||||
Get,
|
||||
|
||||
Cons,
|
||||
Car,
|
||||
Cdr,
|
||||
Quote,
|
||||
Assert,
|
||||
|
||||
Eq,
|
||||
Lt,
|
||||
LEq,
|
||||
Gt,
|
||||
GEq,
|
||||
|
||||
Plus,
|
||||
Minus,
|
||||
Mult,
|
||||
Div,
|
||||
Mod,
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
|
||||
CombP,
|
||||
CellP,
|
||||
PairP,
|
||||
SymbolP,
|
||||
IntP,
|
||||
BoolP,
|
||||
NilP,
|
||||
}
|
||||
|
||||
32
kv/src/grammar.lalrpop
Normal file
@@ -0,0 +1,32 @@
|
||||
use std::str::FromStr;
|
||||
use std::rc::Rc;
|
||||
use crate::basic::Form;
|
||||
use crate::eval::FormT;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Term: Rc<Form> = {
|
||||
NUM => Rc::new(Form::Int(i32::from_str(<>).unwrap())),
|
||||
SYM => Rc::new(Form::Symbol(<>.to_owned())),
|
||||
"(" <ListInside?> ")" => <>.unwrap_or(Rc::new(Form::Nil)),
|
||||
"'" <Term> => Rc::new(Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(Form::Pair(<>, Rc::new(Form::Nil))))),
|
||||
"!" <h: Term> <t: Term> => {
|
||||
h.append(t).unwrap()
|
||||
},
|
||||
};
|
||||
ListInside: Rc<Form> = {
|
||||
<Term> => Rc::new(Form::Pair(<>, Rc::new(Form::Nil))),
|
||||
<h: Term> <t: ListInside> => Rc::new(Form::Pair(h, t)),
|
||||
<a: Term> "." <d: Term> => Rc::new(Form::Pair(a, d)),
|
||||
}
|
||||
match {
|
||||
"(",
|
||||
")",
|
||||
".",
|
||||
"'",
|
||||
"!",
|
||||
r"[0-9]+" => NUM,
|
||||
r"[a-zA-Z+*/_=?%&|^<>-][\w+*/=_?%&|^<>-]*" => SYM,
|
||||
r"(;[^\n]*\n)|\s+" => { }
|
||||
}
|
||||
|
||||
31
kv/src/main.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
#[macro_use] extern crate lalrpop_util;
|
||||
lalrpop_mod!(pub grammar);
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
mod basic;
|
||||
use crate::basic::{root_env,Form};
|
||||
mod eval;
|
||||
use crate::eval::{eval};
|
||||
mod opt;
|
||||
use crate::opt::{OptForm};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
fn main() {
|
||||
//let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))";
|
||||
//let input = "(+ 1 3)";
|
||||
let input = "(= (+ 1 3) (* 2 2))";
|
||||
let parsed_input = grammar::TermParser::new().parse(input).unwrap();
|
||||
//println!("Parsed input is {} - {:?}", parsed_input, parsed_input);
|
||||
let root = root_env();
|
||||
let result = eval(Rc::clone(&root), Rc::clone(&parsed_input));
|
||||
let opt_root: Rc<OptForm> = (&*root).into();
|
||||
let opt_input: Rc<OptForm> = (&*parsed_input).into();
|
||||
let opt_result = eval(opt_root, opt_input);
|
||||
println!("Result is {} - {:?}", result, result);
|
||||
println!("Opt Result is {} - {:?}", opt_result, opt_result);
|
||||
assert!(opt_result.congruent(&*result));
|
||||
}
|
||||
|
||||
294
kv/src/opt.rs
Normal file
@@ -0,0 +1,294 @@
|
||||
use std::fmt;
|
||||
use std::boxed::Box;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::From;
|
||||
|
||||
use crate::eval::{FormT,Cont,Cursor,PrimCombI};
|
||||
use crate::basic::Form;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
struct Trace {}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct OptForm {
|
||||
inner: OptFormInner,
|
||||
trace: Option<Rc<Trace>>
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum OptFormInner {
|
||||
Nil,
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
Symbol(String),
|
||||
Cell(RefCell<Rc<OptForm>>),
|
||||
Pair(Rc<OptForm>,Rc<OptForm>),
|
||||
PrimComb { eval_limit: i32, ins: PrimCombI },
|
||||
DeriComb { se: Rc<OptForm>, de: Option<String>, params: String, body: Rc<OptForm>, code: Option<Rc<RefCell<Vec<ByteCode>>>> },
|
||||
ContComb(Cont<OptForm>),
|
||||
}
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum ByteCode {
|
||||
Ins(PrimCombI)
|
||||
}
|
||||
|
||||
impl fmt::Display for OptForm {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
OptFormInner::Nil => write!(f, "nil"),
|
||||
OptFormInner::Int(i) => write!(f, "{i}"),
|
||||
OptFormInner::Bool(b) => write!(f, "{b}"),
|
||||
OptFormInner::Symbol(s) => write!(f, "{s}"),
|
||||
OptFormInner::Cell(c) => write!(f, "@{}", c.borrow()),
|
||||
OptFormInner::Pair(car, cdr) => {
|
||||
write!(f, "({}", car)?;
|
||||
let mut traverse: Rc<OptForm> = Rc::clone(cdr);
|
||||
loop {
|
||||
match &traverse.inner {
|
||||
OptFormInner::Pair(ref carp, ref cdrp) => {
|
||||
write!(f, " {}", carp)?;
|
||||
traverse = Rc::clone(cdrp);
|
||||
},
|
||||
OptFormInner::Nil => {
|
||||
write!(f, ")")?;
|
||||
return Ok(());
|
||||
},
|
||||
x => {
|
||||
write!(f, ". {})", traverse)?;
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
OptFormInner::PrimComb { eval_limit, ins } => write!(f, "<{eval_limit}> - {ins:?}"),
|
||||
OptFormInner::DeriComb { se: _, de, params, body, code: _ } => {
|
||||
write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body)
|
||||
},
|
||||
OptFormInner::ContComb(_) => write!(f, "<cont>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Form> for Rc<OptForm> {
|
||||
fn from(x: &Form) -> Self {
|
||||
match x {
|
||||
Form::Nil => OptForm::new(OptFormInner::Nil, None),
|
||||
Form::Int(i) => OptForm::new(OptFormInner::Int(*i), None),
|
||||
Form::Bool(b) => OptForm::new(OptFormInner::Bool(*b), None),
|
||||
Form::Symbol(s) => OptForm::new(OptFormInner::Symbol(s.to_owned()), None),
|
||||
Form::Cell(cell) => panic!("bad"),
|
||||
Form::Pair(car,cdr) => OptForm::new(OptFormInner::Pair((&**car).into(), (&**cdr).into()), None),
|
||||
Form::PrimComb { eval_limit, ins } => OptForm::new(OptFormInner::PrimComb { eval_limit: *eval_limit, ins: *ins }, None),
|
||||
Form::DeriComb { .. } => panic!("bad"),
|
||||
Form::ContComb(c) => panic!("bad"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OptForm {
|
||||
fn tc(&self) -> Option<Rc<Trace>> {
|
||||
self.trace.as_ref().map(Rc::clone)
|
||||
}
|
||||
fn tor(&self, o: &Rc<OptForm>) -> Option<Rc<Trace>> {
|
||||
match &self.trace {
|
||||
Some(t) => Some(Rc::clone(t)),
|
||||
None => o.trace.as_ref().map(Rc::clone)
|
||||
}
|
||||
}
|
||||
fn new(inner: OptFormInner, trace: Option<Rc<Trace>>) -> Rc<Self> { Rc::new(OptForm { inner, trace }) }
|
||||
fn truthy(&self) -> bool {
|
||||
match &self.inner {
|
||||
OptFormInner::Bool(b) => *b,
|
||||
OptFormInner::Nil => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
fn int(&self) -> Option<i32> {
|
||||
match &self.inner {
|
||||
OptFormInner::Int(i) => Some(*i),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn append(&self, x: Rc<OptForm>) -> Option<Rc<OptForm>> {
|
||||
let trace = self.tor(&x);
|
||||
match &self.inner {
|
||||
OptFormInner::Pair(car, cdr) => cdr.append(x).map(|x| OptForm::new(OptFormInner::Pair(Rc::clone(car), x), trace)),
|
||||
OptFormInner::Nil => Some(OptForm::new(OptFormInner::Pair(x, OptForm::new(OptFormInner::Nil, trace.as_ref().map(Rc::clone))), trace)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn congruent(&self, other: &Form) -> bool {
|
||||
match other {
|
||||
Form::Nil => self.inner == OptFormInner::Nil,
|
||||
Form::Int(i) => self.inner == OptFormInner::Int(*i),
|
||||
Form::Bool(b) => self.inner == OptFormInner::Bool(*b),
|
||||
Form::Symbol(s) => self.inner == OptFormInner::Symbol(s.to_owned()),
|
||||
Form::Cell(cell) => panic!("bad"),
|
||||
Form::Pair(car,cdr) => match &self.inner { OptFormInner::Pair(carp, cdrp) => carp.congruent(car) && cdrp.congruent(cdr), _ => false },
|
||||
Form::PrimComb { eval_limit, ins } => self.inner == OptFormInner::PrimComb { eval_limit: *eval_limit, ins: *ins },
|
||||
Form::DeriComb { .. } => panic!("bad"),
|
||||
Form::ContComb(c) => panic!("bad"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FormT for OptForm {
|
||||
fn sym(&self) -> Option<&str> {
|
||||
match &self.inner {
|
||||
OptFormInner::Symbol(s) => Some(s),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn pair(&self) -> Option<(Rc<OptForm>,Rc<OptForm>)> {
|
||||
match &self.inner {
|
||||
OptFormInner::Pair(car, cdr) => Some((Rc::clone(car),Rc::clone(cdr))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn car(&self) -> Option<Rc<OptForm>> {
|
||||
match &self.inner {
|
||||
OptFormInner::Pair(car, _cdr) => Some(Rc::clone(car)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn cdr(&self) -> Option<Rc<OptForm>> {
|
||||
match &self.inner {
|
||||
OptFormInner::Pair(_car, cdr) => Some(Rc::clone(cdr)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn is_nil(&self) -> bool {
|
||||
match &self.inner {
|
||||
OptFormInner::Nil => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn call(&self, p: Rc<Self>, e: Rc<Self>, nc: Box<Cont<Self>>, metac: Cont<Self>) -> Cursor<Self> {
|
||||
match &self.inner {
|
||||
OptFormInner::PrimComb{eval_limit, ins} => {
|
||||
Cursor { f: OptForm::new(OptFormInner::Nil, None), c: Cont::PramEval { eval_limit: *eval_limit, to_eval: p, collected: None, e, ins: *ins, nc: nc }, metac }
|
||||
}
|
||||
OptFormInner::DeriComb {se, de, params, body, code} => {
|
||||
// TODO: Add traces here?
|
||||
let mut new_e = Rc::clone(se);
|
||||
if let Some(de) = de {
|
||||
new_e = assoc(&de, Rc::clone(&e), new_e);
|
||||
}
|
||||
new_e = assoc(¶ms, p, new_e);
|
||||
Cursor { f: Rc::clone(body), c: Cont::Eval { e: new_e, nc: nc }, metac }
|
||||
}
|
||||
OptFormInner::ContComb(c) => {
|
||||
// TODO: Add traces here?
|
||||
Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } }
|
||||
}
|
||||
_ => {
|
||||
panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", self, nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn impl_prim(ins: PrimCombI, e: Rc<Self>, ps: Vec<Rc<Self>>, c: Cont<Self>, metac: Cont<Self>) -> Cursor<Self> {
|
||||
match ins {
|
||||
PrimCombI::Eval => Cursor { f: Rc::clone(&ps[0]), c: Cont::Eval { e: Rc::clone(&ps[1]), nc: Box::new(c) }, metac },
|
||||
PrimCombI::Vau => {
|
||||
// Add traces here? If no on-going?
|
||||
let de = ps[0].sym().map(|s| s.to_owned());
|
||||
let params = ps[1].sym().unwrap().to_owned();
|
||||
let body = Rc::clone(&ps[2]);
|
||||
Cursor { f: OptForm::new(OptFormInner::DeriComb { se: e, de, params, body, code: Some(Rc::new(RefCell::new(vec![]))) }, None), c, metac }
|
||||
},
|
||||
PrimCombI::If => if ps[0].truthy() {
|
||||
Cursor { f: Rc::clone(&ps[1]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
} else {
|
||||
Cursor { f: Rc::clone(&ps[2]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
},
|
||||
|
||||
PrimCombI::Reset => Cursor { f: Rc::clone(&ps[0]),
|
||||
c: Cont::Eval { e: e, nc: Box::new(Cont::MetaRet) },
|
||||
metac: Cont::CatchRet { nc: Box::new(c), restore_meta: Box::new(metac) } },
|
||||
PrimCombI::Shift => Cursor { f: Rc::clone(&ps[0]),
|
||||
// Trace here
|
||||
c: Cont::Call { p: OptForm::new(OptFormInner::Pair(OptForm::new(OptFormInner::ContComb(c), None),
|
||||
OptForm::new(OptFormInner::Nil, None)), None),
|
||||
e: e,
|
||||
nc: Box::new(Cont::MetaRet) },
|
||||
metac: Cont::CatchRet { nc: Box::new(metac.clone()), restore_meta: Box::new(metac) } },
|
||||
PrimCombI::Assert => {
|
||||
let thing = Rc::clone(&ps[0]);
|
||||
if !thing.truthy() {
|
||||
println!("Assert failed: {:?}", thing);
|
||||
}
|
||||
assert!(thing.truthy());
|
||||
Cursor { f: Rc::clone(&ps[1]), c: Cont::Eval { e: e, nc: Box::new(c) }, metac }
|
||||
},
|
||||
|
||||
PrimCombI::Cell => Cursor { f: OptForm::new(OptFormInner::Cell(RefCell::new(Rc::clone(&ps[0]))), ps[0].tc()), c, metac },
|
||||
PrimCombI::Set => match &ps[0].inner {
|
||||
OptFormInner::Cell(cell) => Cursor { f: cell.replace(Rc::clone(&ps[1])), c, metac },
|
||||
_ => panic!("set on not cell"),
|
||||
},
|
||||
PrimCombI::Get => match &ps[0].inner {
|
||||
OptFormInner::Cell(cell) => Cursor { f: Rc::clone(&cell.borrow()), c, metac },
|
||||
_ => panic!("get on not cell"),
|
||||
},
|
||||
|
||||
PrimCombI::Cons => Cursor { f: OptForm::new(OptFormInner::Pair(Rc::clone(&ps[0]), Rc::clone(&ps[1])), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Car => Cursor { f: ps[0].car().unwrap(), c, metac },
|
||||
PrimCombI::Cdr => Cursor { f: ps[0].cdr().unwrap(), c, metac },
|
||||
PrimCombI::Quote => Cursor { f: Rc::clone(&ps[0]), c, metac },
|
||||
|
||||
PrimCombI::Eq => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0] == ps[1]), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Lt => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0].int().unwrap() < ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::LEq => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0].int().unwrap() <= ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Gt => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0].int().unwrap() > ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::GEq => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0].int().unwrap() >= ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
|
||||
PrimCombI::Plus => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() + ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Minus => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() - ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Mult => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() * ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Div => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() / ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Mod => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() % ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::And => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() & ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Or => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() | ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
PrimCombI::Xor => Cursor { f: OptForm::new(OptFormInner::Int(ps[0].int().unwrap() ^ ps[1].int().unwrap()), ps[0].tor(&ps[1])), c, metac },
|
||||
|
||||
PrimCombI::CombP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::PrimComb { .. } => true,
|
||||
OptFormInner::DeriComb { .. } => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::CellP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::Cell(_c) => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::PairP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::Pair(_a,_b) => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::SymbolP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::Symbol(_) => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::IntP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::Int(_) => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::BoolP => Cursor { f: OptForm::new(OptFormInner::Bool(match &ps[0].inner {
|
||||
OptFormInner::Bool(_) => true,
|
||||
_ => false,
|
||||
}), ps[0].tc()), c, metac },
|
||||
PrimCombI::NilP => Cursor { f: OptForm::new(OptFormInner::Bool(ps[0].is_nil()), ps[0].tc()), c, metac },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assoc(k: &str, v: Rc<OptForm>, l: Rc<OptForm>) -> Rc<OptForm> {
|
||||
let at = v.tc();
|
||||
let bt = v.tc();
|
||||
let tort = v.tor(&l);
|
||||
OptForm::new(OptFormInner::Pair(
|
||||
OptForm::new(OptFormInner::Pair(
|
||||
OptForm::new(OptFormInner::Symbol(k.to_owned()), at),
|
||||
v), bt),
|
||||
l), tort)
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::grammar;
|
||||
use crate::ast::{eval,root_env,Form,PossibleTailCall};
|
||||
use crate::pe_ast::{mark,partial_eval,new_base_ctxs,MarkedForm};
|
||||
use crate::basic::{root_env,Form};
|
||||
use crate::opt::{OptForm};
|
||||
use crate::eval::{eval};
|
||||
|
||||
#[test]
|
||||
fn parse_test() {
|
||||
@@ -21,36 +22,18 @@ fn parse_test() {
|
||||
|
||||
fn eval_test<T: Into<Form>>(also_pe: bool, gram: &grammar::TermParser, e: &Rc<Form>, code: &str, expected: T) {
|
||||
println!("Doing test {}", code);
|
||||
let parsed = Rc::new(gram.parse(code).unwrap());
|
||||
let parsed = gram.parse(code).unwrap();
|
||||
let basic_result = eval(Rc::clone(e), Rc::clone(&parsed));
|
||||
assert_eq!(*basic_result, expected.into());
|
||||
if also_pe {
|
||||
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, marked_basic_result) = mark(basic_result,bctx);
|
||||
println!("Final PE {}", ped);
|
||||
println!("wanted {}", marked_basic_result);
|
||||
assert_eq!(*ped, *marked_basic_result);
|
||||
}
|
||||
}
|
||||
fn partial_eval_test(gram: &grammar::TermParser, code: &str, expected: &str) {
|
||||
println!("Doing PE test {}", code);
|
||||
let parsed = Rc::new(gram.parse(code).unwrap());
|
||||
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();
|
||||
println!("Final PE {}", ped);
|
||||
println!("wanted {}", expected);
|
||||
assert_eq!(format!("{}", ped), expected);
|
||||
}
|
||||
#[test]
|
||||
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]");
|
||||
|
||||
let opt_root: Rc<OptForm> = (&**e).into();
|
||||
let opt_input: Rc<OptForm> = (&*parsed).into();
|
||||
let opt_result = eval(opt_root, opt_input);
|
||||
assert!(opt_result.congruent(&*basic_result));
|
||||
|
||||
|
||||
//if also_pe {
|
||||
//}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -101,6 +84,19 @@ fn basic_eval_test() { let g = grammar::TermParser::new(); let e = root_env();
|
||||
|
||||
eval_test(true, &g, &e, "((vau root_env _ (eval 'a (cons (cons 'a 2) root_env))))", 2);
|
||||
eval_test(true, &g, &e, "'name-dash", "name-dash");
|
||||
|
||||
eval_test(true, &g, &e, "(get (cell 1))", 1);
|
||||
eval_test(true, &g, &e, "(set (cell 1) 2)", 1);
|
||||
eval_test(true, &g, &e, "(cell? (cell 1))", true);
|
||||
eval_test(true, &g, &e, "((vau de p (eval (quote (cons (set a 2) (get a))) (cons (cons (quote a) (cell 1)) de))))", (1,2));
|
||||
|
||||
eval_test(true, &g, &e, "(reset 1)", 1);
|
||||
eval_test(true, &g, &e, "(reset (+ 1 2))", 3);
|
||||
eval_test(true, &g, &e, "(reset (+ 1 (shift (vau de p 2))))", 2);
|
||||
eval_test(true, &g, &e, "(reset (+ 1 (shift (vau de p ((car p) 2)))))", 3);
|
||||
eval_test(true, &g, &e, "(reset (+ 1 (shift (vau de p ((car p) ((car p) 2)) ))))", 4);
|
||||
eval_test(true, &g, &e, "(reset (+ 1 (shift (vau de p (+ ((car p) 3) ((car p) ((car p) 2))) ))))", 8);
|
||||
eval_test(true, &g, &e, "((reset (+ 1 (shift (vau de p (car p))))) 2)", 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,36 +108,6 @@ static LET: Lazy<String> = Lazy::new(|| {
|
||||
) root_env))))".to_owned()
|
||||
});
|
||||
|
||||
#[test]
|
||||
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), "NeededIds { heads: {}, tails: {}, body_stopped: {}, if_stopped: {} }#[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]");
|
||||
/*
|
||||
partial_eval_test(&g, &format!("{}
|
||||
(vau 0 p
|
||||
!(let1 a 2)
|
||||
!(let1 b 5)
|
||||
(+ b a)
|
||||
)
|
||||
", *LET), "None({})#[None/None/EnvID(0)/0/[]/Some(\"p\")/7]");
|
||||
partial_eval_test(&g, &format!("{}
|
||||
(vau d p
|
||||
!(let1 a 2)
|
||||
(+ (eval (car p) d) a)
|
||||
)
|
||||
", *LET), "None({})#[None/None/EnvID(2)/0/[]/Some(\"p\")/7]");
|
||||
*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fib_eval_test() { let g = grammar::TermParser::new(); let e = root_env();
|
||||
@@ -374,19 +340,19 @@ static BVAU: Lazy<String> = Lazy::new(|| {
|
||||
#[test]
|
||||
fn bvau_eval_test() { let g = grammar::TermParser::new(); let e = root_env();
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau _ (a b c) (+ a (- b c))) 10 2 3)", *BVAU), 9);
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau (a b c) (+ a (- b c))) 10 2 3)", *BVAU), 9);
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau (a b c) (+ a (- b c))) 10 2 3)", *BVAU), 9);
|
||||
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2 3)", *BVAU), (3, Form::Nil));
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2)", *BVAU), Form::Nil);
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau c c) 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau c c))", *BVAU), Form::Nil);
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) c) (10 2) 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) a) (10 2) 3 4 5)", *BVAU), 10);
|
||||
//eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) b) (10 2) 3 4 5)", *BVAU), 2);
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2 3)", *BVAU), (3, Form::Nil));
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2)", *BVAU), Form::Nil);
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau (a b . c) c) 10 2 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau c c) 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau c c))", *BVAU), Form::Nil);
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) c) (10 2) 3 4 5)", *BVAU), (3, (4, (5, Form::Nil))));
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) a) (10 2) 3 4 5)", *BVAU), 10);
|
||||
eval_test(true, &g, &e, &format!("{} ((bvau ((a b) . c) b) (10 2) 3 4 5)", *BVAU), 2);
|
||||
|
||||
//eval_test(true, &g, &e, &format!("{} ((wrap (bvau _ (a b c) (+ a (- b c)))) (+ 10 1) (+ 2 2) (+ 5 3))", *BVAU), 7);
|
||||
//eval_test(true, &g, &e, &format!("{} ((wrap (bvau (a b c) (+ a (- b c)))) (+ 10 1) (+ 2 2) (+ 5 3))", *BVAU), 7);
|
||||
eval_test(true, &g, &e, &format!("{} ((wrap (bvau _ (a b c) (+ a (- b c)))) (+ 10 1) (+ 2 2) (+ 5 3))", *BVAU), 7);
|
||||
eval_test(true, &g, &e, &format!("{} ((wrap (bvau (a b c) (+ a (- b c)))) (+ 10 1) (+ 2 2) (+ 5 3))", *BVAU), 7);
|
||||
}
|
||||
|
||||
static LAMBDA: Lazy<String> = Lazy::new(|| {
|
||||
@@ -1,175 +0,0 @@
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
if (vau de (con than & else) (eval (array cond con than
|
||||
true (cond (> (len else) 0) (idx else 0)
|
||||
true false)) de))
|
||||
|
||||
map (lambda (f5 l5)
|
||||
(let (helper (rec-lambda recurse (f4 l4 n4 i4)
|
||||
(cond (= i4 (len l4)) n4
|
||||
(<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array
|
||||
(f4 (idx l4 (+ i4 0)))
|
||||
(f4 (idx l4 (+ i4 1)))
|
||||
(f4 (idx l4 (+ i4 2)))
|
||||
(f4 (idx l4 (+ i4 3)))
|
||||
)) (+ i4 4))
|
||||
true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1)))))
|
||||
(helper f5 l5 (array) 0)))
|
||||
|
||||
|
||||
map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(cond (= i (len l)) n
|
||||
(<= i (- (len l) 4)) (recurse f l (concat n (array
|
||||
(f (+ i 0) (idx l (+ i 0)))
|
||||
(f (+ i 1) (idx l (+ i 1)))
|
||||
(f (+ i 2) (idx l (+ i 2)))
|
||||
(f (+ i 3) (idx l (+ i 3)))
|
||||
)) (+ i 4))
|
||||
true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
filter_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1))
|
||||
(recurse f l n (+ i 1))))))
|
||||
(helper f l (array) 0)))
|
||||
filter (lambda (f l) (filter_i (lambda (i x) (f x)) l))
|
||||
|
||||
; Huge thanks to Oleg Kiselyov for his fantastic website
|
||||
; http://okmij.org/ftp/Computation/fixed-point-combinators.html
|
||||
Y* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l))))
|
||||
vY* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l))))
|
||||
|
||||
let-rec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
let-vrec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
|
||||
flat_map (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
flat_map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f i (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
; with all this, we make a destrucutring-capable let
|
||||
let (let (
|
||||
destructure_helper (rec-lambda recurse (vs i r)
|
||||
(cond (= (len vs) i) r
|
||||
(array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i)))
|
||||
new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i))
|
||||
)
|
||||
(recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1))))))
|
||||
true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2))))
|
||||
))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de)))
|
||||
|
||||
nil (array)
|
||||
not (lambda (x) (if x false true))
|
||||
or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1)))))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp)))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
|
||||
|
||||
|
||||
foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z
|
||||
(recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1)))))
|
||||
(lambda (f z & vs) (helper f z vs 0)))
|
||||
foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z
|
||||
(lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs))))))
|
||||
(lambda (f z & vs) (helper f z vs 0)))
|
||||
reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x))
|
||||
zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs)))
|
||||
|
||||
match (let (
|
||||
evaluate_case (rec-lambda evaluate_case (access c) (cond
|
||||
(symbol? c) (array true (lambda (b) (array let (array c access) b)))
|
||||
(and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b))
|
||||
(and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b))
|
||||
(array? c) (let (
|
||||
tests (array and (array array? access) (array = (len c) (array len access)))
|
||||
(tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c))
|
||||
(array tests body_func)
|
||||
(let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) )
|
||||
(recurse (concat tests (array inner_test))
|
||||
(lambda (b) (body_func (inner_body_func b)))
|
||||
(+ i 1)))))
|
||||
tests (lambda (b) b) 0)
|
||||
) (array tests body_func))
|
||||
true (array (array = access c) (lambda (b) b))
|
||||
))
|
||||
helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) )
|
||||
(concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2))))
|
||||
true (array true (array error "none matched"))))
|
||||
) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de)))
|
||||
|
||||
ll-nil nil
|
||||
ll-cons array
|
||||
ll-make (rec-lambda ll-make (n) (if (= 0 n) ll-nil
|
||||
(ll-cons n (ll-make (- n 1)))))
|
||||
ll-sum (rec-lambda ll-sum (l) (match l
|
||||
,nil 0
|
||||
(hh (h t)) (+ h hh (ll-sum t))
|
||||
(h t) (+ h (ll-sum t))
|
||||
))
|
||||
|
||||
|
||||
monad (array 'write 1 (str "running tree test") (vau (written code)
|
||||
(array 'args (vau (args code)
|
||||
;(array 'exit (log (reduce-test-tree (make-test-tree (read-string (idx args 1)) map-empty))))
|
||||
(array 'exit (log (let (l (ll-make (read-string (idx args 1)))
|
||||
_ (log "swapping to sum")
|
||||
) (ll-sum l))))
|
||||
))
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
fact (rec-lambda fact (n) (cond (= 0 n) 1
|
||||
(= 1 n) 1
|
||||
true (* n (fact (- n 1)))))
|
||||
|
||||
monad (array 'write 1 "enter number to fact: " (vau (written code)
|
||||
(array 'read 0 60 (vau (data code)
|
||||
(array 'exit (fact (read-string data)))
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
;fact (rec-lambda fact (n) (cond (= 0 n) 1
|
||||
; (= 1 n) 1
|
||||
; true (band #xFFFFFF (* n (fact (- n 1))))))
|
||||
fact (rec-lambda fact (n r) (cond (= 0 n) r
|
||||
(= 1 n) r
|
||||
true (fact (- n 1) (band #xFFFFFF (* n r)))))
|
||||
|
||||
monad (array 'write 1 "hao" (vau (written code)
|
||||
(array 'exit (log (fact (log 10000) 1)))
|
||||
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,110 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
cdr (lambda (x) (slice x 1 -1))
|
||||
if (vau de (con than & else) (eval (array cond con than
|
||||
true (cond (> (len else) 0) (idx else 0)
|
||||
true false)) de))
|
||||
and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp)))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
|
||||
; if len(s1) > 0 && len(sub) > 0:
|
||||
; char1 = s1[0]
|
||||
; rest1 = s1[1:]
|
||||
; char2 = sub[0]
|
||||
; rest2 = sub[1:]
|
||||
; if char1 == char2:
|
||||
; return recurse(rest1, rest2)
|
||||
; else
|
||||
; return false
|
||||
; else if len(s1) > 0 && len(sub) == 0:
|
||||
; return true
|
||||
; else if len(s1) == 0:
|
||||
; return false
|
||||
; else:
|
||||
; return false
|
||||
;
|
||||
;
|
||||
compare_substr (rec-lambda cmp (str1 str2) (let (
|
||||
str1_len (len str1)
|
||||
str2_len (len str2))
|
||||
; len(s1) > 0 && len(sub) > 0
|
||||
(cond (and (> str1_len 0) (> str2_len 0))
|
||||
(let (
|
||||
char1 (idx str1 0)
|
||||
rest1 (cdr str1)
|
||||
char2 (idx str2 0)
|
||||
rest2 (cdr str2)
|
||||
same_char (= char1 char2)
|
||||
; if char1 == char2: return recurse(str, sub)
|
||||
; else: return false
|
||||
) (cond same_char (cmp rest1 rest2)
|
||||
true false
|
||||
))
|
||||
; len(s1) > 0 && len(sub) == 0
|
||||
(and (> str1_len 0) (= str2_len 0)) true
|
||||
; else
|
||||
true false
|
||||
)
|
||||
))
|
||||
; i = index of current match start, passed in
|
||||
; len1 = len(str)
|
||||
; len2 = len(sub)
|
||||
;
|
||||
; if len2 > len1:
|
||||
; return -1
|
||||
; else if len1 > 0 && len2 == 0:
|
||||
; // No more substr, we matched?
|
||||
; return i
|
||||
; else if len1 > 0 && len2 > 0:
|
||||
; if compare(str, sub):
|
||||
; return i
|
||||
; else:
|
||||
; rest1 = str[1:]
|
||||
; return recurse(rest1, sub, i+1)
|
||||
; else
|
||||
; return -1
|
||||
;
|
||||
_find (rec-lambda _find (str sub i) (let (
|
||||
len1 (len str)
|
||||
len2 (len sub)
|
||||
) (cond (> len2 len1) -1
|
||||
(= len2 0) i
|
||||
(and (> len1 0) (> len2 0)) (cond (compare_substr str sub) i
|
||||
true (_find (cdr str) sub (+ i 1)))
|
||||
true -1
|
||||
)))
|
||||
; find the index of a substr in a str
|
||||
; check if a substr is in a str
|
||||
find (lambda (str sub) (_find str sub 0))
|
||||
contains (lambda (str sub) (!= (find str sub) -1))
|
||||
|
||||
monad (array 'write 1 "testing find funcs: \n" (vau (written code)
|
||||
(array 'write 1 "find in \"foobar\" the string \"oba\"\n" (vau (written code)
|
||||
(array 'write 1 (concat (str (contains "foobar" "oba")) "\n") (vau (written code)
|
||||
(array 'exit 0)))
|
||||
))
|
||||
))
|
||||
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
; Some helper hex literals
|
||||
xF 15
|
||||
xF0 240
|
||||
xFF 255
|
||||
xFF00 65280
|
||||
xFFFF 65535
|
||||
xFFFF0000 4294901760
|
||||
|
||||
; nibble to hex digit
|
||||
nibble_to_hexstr(lambda (n)
|
||||
(cond (= n 15) "f"
|
||||
(= n 14) "e"
|
||||
(= n 13) "d"
|
||||
(= n 12) "c"
|
||||
(= n 11) "b"
|
||||
(= n 10) "a"
|
||||
true (str n))
|
||||
)
|
||||
; char to hex str
|
||||
char_to_hexstr (lambda (c)
|
||||
(concat
|
||||
(nibble_to_hexstr (>> (band c xF0) 4))
|
||||
(nibble_to_hexstr (band c xF)))
|
||||
)
|
||||
; short to hex str
|
||||
short_to_hexstr (lambda (s)
|
||||
(concat
|
||||
(char_to_hexstr (>> (band s xFF00) 8))
|
||||
(char_to_hexstr (band s xFF)))
|
||||
)
|
||||
; 32 bit int to hex string helper
|
||||
int_to_hexstr (lambda (i)
|
||||
(str
|
||||
(concat
|
||||
(short_to_hexstr (>> (band i xFFFF0000) 16))
|
||||
(short_to_hexstr (band i xFFFF)))
|
||||
)
|
||||
)
|
||||
|
||||
monad (array 'write 1 "enter int to get hex string: " (vau (written code)
|
||||
(array 'read 0 60 (vau (num code)
|
||||
(array 'write 1 (concat (int_to_hexstr (read-string num)) "\n") (vau (written code)
|
||||
(array 'exit 0)
|
||||
))))))
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
|
||||
; bitwise left rotate
|
||||
leftrotate (lambda (i shift_amt)
|
||||
; Rotate i left by shift amt
|
||||
(bor (<< i shift_amt) (>> i (- 32 shift_amt)))
|
||||
)
|
||||
|
||||
monad (array 'write 1 "enter int to left rotate: " (vau (written code)
|
||||
(array 'read 0 60 (vau (num code)
|
||||
(array 'write 1 "enter rotate amount: " (vau (written code)
|
||||
(array 'read 0 60 (vau (amount code)
|
||||
(array 'write 1 (concat (str (leftrotate (read-string num) (read-string amount))) "\n") (vau (written code)
|
||||
(array 'exit 0)
|
||||
))))))))))
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
palindrome (rec-lambda palindrome (s) (let (
|
||||
; _ (log "palindrome called")
|
||||
length (- (len s) 1) ; -1 because we don't care about \n chars
|
||||
; _ (log "length is" (str length))
|
||||
) (cond (= length 0) true
|
||||
(= length 1) true
|
||||
true (let (
|
||||
; _ (log "getting first + last chars")
|
||||
first (idx s 0)
|
||||
last (idx s (- length 1))
|
||||
; _ (log "Checking chars")
|
||||
; _ (log first " == " last)
|
||||
)(cond (!= first last) false
|
||||
true (palindrome (slice s 1 -2)))
|
||||
)
|
||||
)))
|
||||
palindrome_wrap (lambda (s) (cond (palindrome s) (concat "TRUE! " s " is a palindrome!!\n")
|
||||
true (concat "FALSE! " s " is not a palindrome!!\n")))
|
||||
|
||||
|
||||
monad (array 'write 1 "enter string to check if it is a palindrome: " (vau (written code)
|
||||
(array 'read 0 60 (vau (s code)
|
||||
(array 'write 1 (palindrome_wrap s) (vau (written code)
|
||||
(array 'exit 0)
|
||||
))))))
|
||||
) monad)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,15 +0,0 @@
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
|
||||
|
||||
(array 'write 1 "enter form: " (vau (written code)
|
||||
(array 'read 0 200 (vau (data code)
|
||||
((wrap (vau (asdf) (array 'exit (log (eval (log (read-string data))))))) code)
|
||||
;((wrap (vau (asdf) (array 'exit (eval (read-string data))))) code)
|
||||
;((wrap (vau (asdf) (array 'exit (cond (log "hi") written true code)))) code)
|
||||
))
|
||||
|
||||
))
|
||||
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,917 +0,0 @@
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env)))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
;if (vau de (con than & else) (cond (eval con de) (eval than de)
|
||||
; (> (len else) 0) (eval (idx else 0) de)
|
||||
; true false))
|
||||
if (vau de (con than & else) (eval (array cond con than
|
||||
true (cond (> (len else) 0) (idx else 0)
|
||||
true false)) de))
|
||||
|
||||
map (lambda (f5 l5)
|
||||
; now maybe errors on can't find helper?
|
||||
(let (helper (rec-lambda recurse (f4 l4 n4 i4)
|
||||
(cond (= i4 (len l4)) n4
|
||||
(<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array
|
||||
(f4 (idx l4 (+ i4 0)))
|
||||
(f4 (idx l4 (+ i4 1)))
|
||||
(f4 (idx l4 (+ i4 2)))
|
||||
(f4 (idx l4 (+ i4 3)))
|
||||
)) (+ i4 4))
|
||||
true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1)))))
|
||||
(helper f5 l5 (array) 0)))
|
||||
|
||||
|
||||
map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(cond (= i (len l)) n
|
||||
(<= i (- (len l) 4)) (recurse f l (concat n (array
|
||||
(f (+ i 0) (idx l (+ i 0)))
|
||||
(f (+ i 1) (idx l (+ i 1)))
|
||||
(f (+ i 2) (idx l (+ i 2)))
|
||||
(f (+ i 3) (idx l (+ i 3)))
|
||||
)) (+ i 4))
|
||||
true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
filter_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1))
|
||||
(recurse f l n (+ i 1))))))
|
||||
(helper f l (array) 0)))
|
||||
filter (lambda (f l) (filter_i (lambda (i x) (f x)) l))
|
||||
|
||||
; Huge thanks to Oleg Kiselyov for his fantastic website
|
||||
; http://okmij.org/ftp/Computation/fixed-point-combinators.html
|
||||
Y* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l))))
|
||||
vY* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l))))
|
||||
|
||||
let-rec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
let-vrec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
|
||||
flat_map (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
flat_map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f i (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
; with all this, we make a destrucutring-capable let
|
||||
let (let (
|
||||
destructure_helper (rec-lambda recurse (vs i r)
|
||||
(cond (= (len vs) i) r
|
||||
(array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i)))
|
||||
new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i))
|
||||
)
|
||||
(recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1))))))
|
||||
true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2))))
|
||||
))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de)))
|
||||
|
||||
; and a destructuring-capable lambda!
|
||||
only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true
|
||||
(symbol? (idx a i)) (recurse a (+ i 1))
|
||||
true false))
|
||||
|
||||
; Note that if macro_helper is inlined, the mapping lambdas will close over
|
||||
; se, and then not be able to be taken in as values to the maps, and the vau
|
||||
; will fail to partially evaluate away.
|
||||
lambda (let (macro_helper (lambda (p b) (let (
|
||||
sym_params (map (lambda (param) (if (symbol? param) param
|
||||
(str-to-symbol (str param)))) p)
|
||||
body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b)
|
||||
) (array vau sym_params body))))
|
||||
(vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se)
|
||||
(wrap (eval (macro_helper p b) se)))))
|
||||
|
||||
; and rec-lambda - yes it's the same definition again
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
nil (array)
|
||||
not (lambda (x) (if x false true))
|
||||
or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1)))))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp)))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
|
||||
|
||||
|
||||
foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z
|
||||
(recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1)))))
|
||||
(lambda (f z & vs) (helper f z vs 0)))
|
||||
foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z
|
||||
(lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs))))))
|
||||
(lambda (f z & vs) (helper f z vs 0)))
|
||||
reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x))
|
||||
zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Begin kludges to align with Scheme kludges
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
dlet (vau se (inners body) (vapply let (array (lapply concat inners) body) se))
|
||||
cond (vau se (& inners) (vapply cond (lapply concat inners) se))
|
||||
print log
|
||||
println log
|
||||
dlambda lambda
|
||||
mif (vau de (c & bs) (vapply if (cons (array let (array 'tmp c) (array and (array != 'tmp (array quote (array))) 'tmp)) bs) de))
|
||||
;mif (vau de (c & bs) (eval (concat (array if (array let (array 'tmp c) (array and (array != 'tmp) 'tmp))) bs) de))
|
||||
|
||||
|
||||
)
|
||||
(dlet (
|
||||
|
||||
(empty_dict-list (array))
|
||||
(put-list (lambda (m k v) (cons (array k v) m)))
|
||||
(get-list (lambda (d k) ((rec-lambda recurse (k d len_d i) (cond ((= len_d i) false)
|
||||
((= k (idx (idx d i) 0)) (idx d i))
|
||||
(true (recurse k d len_d (+ 1 i)))))
|
||||
k d (len d) 0)))
|
||||
|
||||
;(combine_hash (lambda (a b) (+ (* 37 a) b)))
|
||||
(combine_hash (lambda (a b) (band #xFFFFFFFFFFFFFF (+ (* 37 a) b))))
|
||||
(hash_bool (lambda (b) (if b 2 3)))
|
||||
(hash_num (lambda (n) (combine_hash 5 n)))
|
||||
;(hash_string (lambda (s) (foldl combine_hash 7 (map char->integer (string->list s)))))
|
||||
(hash_string (lambda (s) (foldl combine_hash 7 s)))
|
||||
;(hash_string (lambda (s) (foldl combine_hash 102233 (map char->integer (string->list s)))))
|
||||
|
||||
(empty_dict-tree nil)
|
||||
(trans-key (lambda (k) (cond ((string? k) (hash_string k))
|
||||
((symbol? k) (hash_string (get-text k)))
|
||||
(true k))))
|
||||
(put-helper (rec-lambda put-helper (m hk k v) (cond ((nil? m) (array hk k v nil nil))
|
||||
((and (= hk (idx m 0))
|
||||
(= k (idx m 1))) (array hk k v (idx m 3) (idx m 4)))
|
||||
((< hk (idx m 0)) (array (idx m 0) (idx m 1) (idx m 2) (put-helper (idx m 3) hk k v) (idx m 4)))
|
||||
(true (array (idx m 0) (idx m 1) (idx m 2) (idx m 3) (put-helper (idx m 4) hk k v))))))
|
||||
(put-tree (lambda (m k v) (put-helper m (trans-key k) k v)))
|
||||
(get-helper (rec-lambda get-helper (m hk k) (cond ((nil? m) false)
|
||||
((and (= hk (idx m 0))
|
||||
(= k (idx m 1))) (array k (idx m 2)))
|
||||
((< hk (idx m 0)) (get-helper (idx m 3) hk k))
|
||||
(true (get-helper (idx m 4) hk k)))))
|
||||
(get-tree (lambda (m k) (get-helper m (trans-key k) k)))
|
||||
|
||||
;(empty_dict empty_dict-list)
|
||||
;(put put-list)
|
||||
;(get get-list)
|
||||
(empty_dict empty_dict-tree)
|
||||
(put put-tree)
|
||||
(get get-tree)
|
||||
|
||||
(get-value (lambda (d k) (dlet ((result (get d k)))
|
||||
(if (array? result) (idx result 1)
|
||||
(error (str "could not find " k " in " d))))))
|
||||
(get-value-or-false (lambda (d k) (dlet ((result (get d k)))
|
||||
(if (array? result) (idx result 1)
|
||||
false))))
|
||||
|
||||
|
||||
|
||||
(in_array (dlet ((helper (rec-lambda recurse (x a len_a i) (cond ((= i len_a) false)
|
||||
((= x (idx a i)) true)
|
||||
(true (recurse x a len_a (+ i 1)))))))
|
||||
(lambda (x a) (helper x a (len a) 0))))
|
||||
(array_item_union (lambda (a bi) (if (in_array bi a) a (cons bi a))))
|
||||
(array_union (lambda (a b) (foldl array_item_union a b)))
|
||||
(array_union_without (lambda (wo a b)
|
||||
(foldl (lambda (o xi) (if (or (= wo xi) (in_array xi o)) o (cons xi o)))
|
||||
(array) (concat a b))))
|
||||
|
||||
; just for now, should just add all normal linked list primitives
|
||||
; as they should be
|
||||
(car (lambda (x) (idx x 0)))
|
||||
(cdr (lambda (x) (slice x 1 -1)))
|
||||
|
||||
(intset_word_size 64)
|
||||
(in_intset (rec-lambda in_intset (x a) (cond ((nil? a) false)
|
||||
((>= x intset_word_size) (in_intset (- x intset_word_size) (cdr a)))
|
||||
(true (!= (band (>> (car a) x) 1) 0)))))
|
||||
|
||||
(intset_item_union (rec-lambda intset_item_union (a bi) (cond ((nil? a) (intset_item_union (array 0) bi))
|
||||
((>= bi intset_word_size) (cons (car a) (intset_item_union (cdr a) (- bi intset_word_size))))
|
||||
(true (cons (bor (car a) (<< 1 bi)) (cdr a))))))
|
||||
|
||||
(intset_item_remove (rec-lambda intset_item_remove (a bi) (cond ((nil? a) nil)
|
||||
((>= bi intset_word_size) (dlet ((new_tail (intset_item_remove (cdr a) (- bi intset_word_size))))
|
||||
(if (and (nil? new_tail) (= 0 (car a))) nil
|
||||
(cons (car a) new_tail))))
|
||||
(true (dlet ((new_int (band (car a) (bnot (<< 1 bi)))))
|
||||
(if (and (nil? (cdr a)) (= 0 new_int)) nil
|
||||
(cons new_int (cdr a))))))))
|
||||
(intset_union (rec-lambda intset_union (a b) (cond ((and (nil? a) (nil? b)) nil)
|
||||
((nil? a) b)
|
||||
((nil? b) a)
|
||||
(true (cons (bor (car a) (car b)) (intset_union (cdr a) (cdr b)))))))
|
||||
|
||||
(intset_intersection_nonempty (rec-lambda intset_intersection_nonempty (a b) (cond ((nil? a) false)
|
||||
((nil? b) false)
|
||||
(true (or (!= 0 (band (car a) (car b))) (intset_intersection_nonempty (cdr a) (cdr b)))))))
|
||||
|
||||
(intset_union_without (lambda (wo a b) (intset_item_remove (intset_union a b) wo)))
|
||||
|
||||
|
||||
(val? (lambda (x) (= 'val (idx x 0))))
|
||||
(marked_array? (lambda (x) (= 'marked_array (idx x 0))))
|
||||
(marked_symbol? (lambda (x) (= 'marked_symbol (idx x 0))))
|
||||
(comb? (lambda (x) (= 'comb (idx x 0))))
|
||||
(prim_comb? (lambda (x) (= 'prim_comb (idx x 0))))
|
||||
(marked_env? (lambda (x) (= 'env (idx x 0))))
|
||||
|
||||
(.hash (lambda (x) (idx x 1)))
|
||||
|
||||
(.val (lambda (x) (idx x 2)))
|
||||
|
||||
(.marked_array_is_val (lambda (x) (idx x 2)))
|
||||
(.marked_array_is_attempted (lambda (x) (idx x 3)))
|
||||
(.marked_array_needed_for_progress (lambda (x) (idx x 4)))
|
||||
(.marked_array_values (lambda (x) (idx x 5)))
|
||||
|
||||
(.marked_symbol_needed_for_progress (lambda (x) (idx x 2)))
|
||||
(.marked_symbol_is_val (lambda (x) (= nil (.marked_symbol_needed_for_progress x))))
|
||||
(.marked_symbol_value (lambda (x) (idx x 3)))
|
||||
(.comb (lambda (x) (slice x 2 -1)))
|
||||
(.comb_id (lambda (x) (idx x 3)))
|
||||
(.comb_des (lambda (x) (idx x 4)))
|
||||
(.comb_env (lambda (x) (idx x 5)))
|
||||
(.comb_body (lambda (x) (idx x 8)))
|
||||
(.comb_wrap_level (lambda (x) (idx x 2)))
|
||||
(.prim_comb_sym (lambda (x) (idx x 3)))
|
||||
(.prim_comb_handler (lambda (x) (idx x 2)))
|
||||
(.prim_comb_wrap_level (lambda (x) (idx x 4)))
|
||||
(.prim_comb_val_head_ok (lambda (x) (idx x 5)))
|
||||
(.prim_comb (lambda (x) (slice x 2 -1)))
|
||||
|
||||
(.marked_env (lambda (x) (slice x 2 -1)))
|
||||
(.marked_env_has_vals (lambda (x) (idx x 2)))
|
||||
(.marked_env_needed_for_progress (lambda (x) (idx x 3)))
|
||||
(.marked_env_idx (lambda (x) (idx x 4)))
|
||||
(.marked_env_upper (lambda (x) (idx (idx x 5) -1)))
|
||||
(.env_marked (lambda (x) (idx x 5)))
|
||||
(marked_env_real? (lambda (x) (= nil (idx (.marked_env_needed_for_progress x) 0))))
|
||||
(.any_comb_wrap_level (lambda (x) (cond ((prim_comb? x) (.prim_comb_wrap_level x))
|
||||
((comb? x) (.comb_wrap_level x))
|
||||
(true (error "bad .any_comb_level")))))
|
||||
; The actual needed_for_progress values are either
|
||||
; #t - any eval will do something
|
||||
; nil - is a value, no eval will do anything
|
||||
; (3 4 1...) - list of env ids that would allow forward progress
|
||||
; But these are paired with another list of hashes that if you're not inside
|
||||
; of an evaluation of, then it could progress futher. These are all caused by
|
||||
; the infinite recursion stopper.
|
||||
(needed_for_progress (rec-lambda needed_for_progress (x) (cond ((marked_array? x) (.marked_array_needed_for_progress x))
|
||||
((marked_symbol? x) (array (.marked_symbol_needed_for_progress x) nil nil))
|
||||
((marked_env? x) (.marked_env_needed_for_progress x))
|
||||
((comb? x) (dlet ((id (.comb_id x))
|
||||
((body_needed _hashes extra1) (needed_for_progress (.comb_body x)))
|
||||
((se_needed _hashes extra2) (needed_for_progress (.comb_env x))))
|
||||
(if (or (= true body_needed) (= true se_needed)) (array true nil nil)
|
||||
(array (array_union_without id body_needed se_needed)
|
||||
nil (array_union_without id extra1 extra2))
|
||||
)))
|
||||
((prim_comb? x) (array nil nil nil))
|
||||
((val? x) (array nil nil nil))
|
||||
(true (error (str "what is this? in need for progress" x))))))
|
||||
(needed_for_progress_slim (lambda (x) (idx (needed_for_progress x) 0)))
|
||||
|
||||
(hash_symbol (lambda (progress_idxs s) (combine_hash (if (= true progress_idxs) 11 (foldl combine_hash 13 (map (lambda (x) (if (= true x) 13 (+ 1 x))) progress_idxs))) (hash_string (get-text s)))))
|
||||
(hash_array (lambda (is_val attempted a) (foldl combine_hash (if is_val 17 (cond ((int? attempted) (combine_hash attempted 19))
|
||||
(attempted 61)
|
||||
(true 107))) (map .hash a))))
|
||||
|
||||
(hash_env (lambda (has_vals progress_idxs dbi arrs) (combine_hash (if has_vals 107 109)
|
||||
(combine_hash (mif dbi (hash_num dbi) 59) (dlet (
|
||||
;(_ (begin (true_print "pre slice " (slice arrs 0 -2)) 0))
|
||||
;(_ (begin (true_print "about to do a fold " progress_idxs " and " (slice arrs 0 -2)) 0))
|
||||
(inner_hash (foldl (dlambda (c (s v)) (combine_hash c (combine_hash (hash_symbol true s) (.hash v))))
|
||||
(cond ((= nil progress_idxs) 23)
|
||||
((= true progress_idxs) 29)
|
||||
(true (foldl combine_hash 31 progress_idxs)))
|
||||
(slice arrs 0 -2)))
|
||||
(end (idx arrs -1))
|
||||
(end_hash (mif end (.hash end) 41))
|
||||
) (combine_hash inner_hash end_hash))))))
|
||||
|
||||
(hash_comb (lambda (wrap_level env_id de? se variadic params body)
|
||||
(combine_hash 43
|
||||
(combine_hash wrap_level
|
||||
(combine_hash env_id
|
||||
(combine_hash (mif de? (hash_symbol true de?) 47)
|
||||
(combine_hash (.hash se)
|
||||
(combine_hash (hash_bool variadic)
|
||||
(combine_hash (foldl (lambda (c x) (combine_hash c (hash_symbol true x))) 53 params)
|
||||
(.hash body))))))))))
|
||||
|
||||
(hash_prim_comb (lambda (handler_fun real_or_name wrap_level val_head_ok) (combine_hash (combine_hash 59 (hash_symbol true real_or_name))
|
||||
(combine_hash (if val_head_ok 89 97) wrap_level))))
|
||||
(hash_val (lambda (x) (cond ((bool? x) (hash_bool x))
|
||||
((string? x) (hash_string x))
|
||||
((int? x) (hash_num x))
|
||||
(true (error (str "bad thing to hash_val " x))))))
|
||||
; 113 127 131 137 139 149 151 157 163 167 173
|
||||
|
||||
(marked_symbol (lambda (progress_idxs x) (array 'marked_symbol (hash_symbol progress_idxs x) progress_idxs x)))
|
||||
(marked_array (lambda (is_val attempted resume_hashes x) (dlet (
|
||||
((sub_progress_idxs hashes extra) (foldl (dlambda ((a ahs aeei) (x xhs x_extra_env_ids))
|
||||
(array (cond ((or (= true a) (= true x)) true)
|
||||
(true (array_union a x)))
|
||||
(array_union ahs xhs)
|
||||
(array_union aeei x_extra_env_ids))
|
||||
) (array (array) resume_hashes (array)) (map needed_for_progress x)))
|
||||
(progress_idxs (cond ((and (= nil sub_progress_idxs) (not is_val) (= true attempted)) nil)
|
||||
((and (= nil sub_progress_idxs) (not is_val) (= false attempted)) true)
|
||||
((and (= nil sub_progress_idxs) (not is_val) (int? attempted)) (array attempted))
|
||||
(true (if (int? attempted)
|
||||
(array_item_union sub_progress_idxs attempted)
|
||||
sub_progress_idxs))))
|
||||
) (array 'marked_array (hash_array is_val attempted x) is_val attempted (array progress_idxs hashes extra) x))))
|
||||
(marked_env (lambda (has_vals de? de ue dbi arrs) (dlet (
|
||||
(de_entry (mif de? (array (array de? de)) (array)))
|
||||
(full_arrs (concat arrs de_entry (array ue)))
|
||||
((progress_idxs1 _hashes extra1) (mif ue (needed_for_progress ue) (array nil nil nil)))
|
||||
((progress_idxs2 _hashes extra2) (mif de? (needed_for_progress de) (array nil nil nil)))
|
||||
(progress_idxs (array_union progress_idxs1 progress_idxs2))
|
||||
(extra (array_union extra1 extra2))
|
||||
(progress_idxs (if (not has_vals) (cons dbi progress_idxs) progress_idxs))
|
||||
(extra (if (!= nil progress_idxs) (cons dbi extra) extra))
|
||||
) (array 'env (hash_env has_vals progress_idxs dbi full_arrs) has_vals (array progress_idxs nil extra) dbi full_arrs))))
|
||||
|
||||
|
||||
(marked_val (lambda (x) (array 'val (hash_val x) x)))
|
||||
(marked_comb (lambda (wrap_level env_id de? se variadic params body) (array 'comb (hash_comb wrap_level env_id de? se variadic params body) wrap_level env_id de? se variadic params body)))
|
||||
(marked_prim_comb (lambda (handler_fun real_or_name wrap_level val_head_ok) (array 'prim_comb (hash_prim_comb handler_fun real_or_name wrap_level val_head_ok) handler_fun real_or_name wrap_level val_head_ok)))
|
||||
|
||||
(with_wrap_level (lambda (x new_wrap) (cond ((prim_comb? x) (dlet (((handler_fun real_or_name wrap_level val_head_ok) (.prim_comb x)))
|
||||
(marked_prim_comb handler_fun real_or_name new_wrap val_head_ok)))
|
||||
((comb? x) (dlet (((wrap_level env_id de? se variadic params body) (.comb x)))
|
||||
(marked_comb new_wrap env_id de? se variadic params body)))
|
||||
(true (error "bad with_wrap_level")))))
|
||||
|
||||
|
||||
(later_head? (rec-lambda recurse (x) (or (and (marked_array? x) (or (= false (.marked_array_is_val x)) (foldl (lambda (a x) (or a (recurse x))) false (.marked_array_values x))))
|
||||
(and (marked_symbol? x) (= false (.marked_symbol_is_val x)))
|
||||
)))
|
||||
|
||||
|
||||
; array and comb are the ones wherewhere (= nil (needed_for_progress_slim x)) == total_value? isn't true.
|
||||
; Right now we only call functions when all parameters are values, which means you can't
|
||||
; create a true_value array with non-value memebers (*right now* anyway), but it does mean that
|
||||
; you can create a nil needed for progress array that isn't a value, namely for the give_up_*
|
||||
; primitive functions (extra namely, log and error, which are our two main sources of non-purity besides implicit runtime errors).
|
||||
; OR, currently, having your code stopped because of infinite recursion checker. This comes up with the Y combiner
|
||||
; For combs, being a value is having your env-chain be real?
|
||||
(total_value? (lambda (x) (if (marked_array? x) (.marked_array_is_val x)
|
||||
(= nil (needed_for_progress_slim x)))))
|
||||
|
||||
(is_all_values (lambda (evaled_params) (foldl (lambda (a x) (and a (total_value? x))) true evaled_params)))
|
||||
(is_all_head_values (lambda (evaled_params) (foldl (lambda (a x) (and a (not (later_head? x)))) true evaled_params)))
|
||||
|
||||
(false? (lambda (x) (cond ((and (marked_array? x) (= false (.marked_array_is_val x))) (error "got a later marked_array passed to false? " x))
|
||||
((and (marked_symbol? x) (= false (.marked_symbol_is_val x))) (error "got a later marked_symbol passed to false? " x))
|
||||
((val? x) (not (.val x)))
|
||||
(true false))))
|
||||
|
||||
|
||||
(mark (rec-lambda recurse (eval_pos x) (cond ((env? x) (error "called mark with an env " x))
|
||||
((combiner? x) (error "called mark with a combiner " x))
|
||||
((symbol? x) (cond ((= 'true x) (marked_val #t))
|
||||
((= 'false x) (marked_val #f))
|
||||
(#t (marked_symbol (if eval_pos true nil) x))))
|
||||
((array? x) (marked_array (not eval_pos) false nil
|
||||
(idx (foldl (dlambda ((ep a) x) (array false (concat a (array (recurse ep x)))))
|
||||
(array eval_pos (array))
|
||||
x)
|
||||
1)
|
||||
))
|
||||
(true (marked_val x)))))
|
||||
|
||||
(indent_str (rec-lambda recurse (i) (mif (= i 0) ""
|
||||
(str " " (recurse (- i 1))))))
|
||||
|
||||
(speed_hack true)
|
||||
(true_str str)
|
||||
(indent_str (if speed_hack (lambda (i) "") indent_str))
|
||||
|
||||
(str_strip (lambda (& args) (lapply true_str (concat (slice args 0 -2) (array (idx ((rec-lambda recurse (x done_envs)
|
||||
(cond ((= nil x) (array "<nil>" done_envs))
|
||||
((string? x) (array (true_str "<raw string " x ">") done_envs))
|
||||
((val? x) (array (true_str (.val x)) done_envs))
|
||||
((marked_array? x) (dlet (((stripped_values done_envs) (foldl (dlambda ((vs de) x) (dlet (((v de) (recurse x de))) (array (concat vs (array v)) de)))
|
||||
(array (array) done_envs) (.marked_array_values x))))
|
||||
(mif (.marked_array_is_val x) (array (true_str "[" stripped_values "]") done_envs)
|
||||
(array (true_str stripped_values) done_envs))))
|
||||
;(array (true_str "<a" (.marked_array_is_attempted x) ",r" (needed_for_progress x) ">" stripped_values) done_envs))))
|
||||
((marked_symbol? x) (mif (.marked_symbol_is_val x) (array (true_str "'" (.marked_symbol_value x)) done_envs)
|
||||
(array (true_str (.marked_symbol_needed_for_progress x) "#" (.marked_symbol_value x)) done_envs)))
|
||||
((comb? x) (dlet (((wrap_level env_id de? se variadic params body) (.comb x))
|
||||
((se_s done_envs) (recurse se done_envs))
|
||||
((body_s done_envs) (recurse body done_envs)))
|
||||
(array (true_str "<n (comb " wrap_level " " env_id " " de? " " se_s " " params " " body_s ")>") done_envs)))
|
||||
((prim_comb? x) (array (true_str "<wl=" (.prim_comb_wrap_level x) " " (.prim_comb_sym x) ">") done_envs))
|
||||
((marked_env? x) (dlet ((e (.env_marked x))
|
||||
(index (.marked_env_idx x))
|
||||
(u (idx e -1))
|
||||
(already (in_array index done_envs))
|
||||
(opening (true_str "{" (mif (marked_env_real? x) "real" "fake") (mif (.marked_env_has_vals x) " real vals" " fake vals") " ENV idx: " (true_str index) ", "))
|
||||
((middle done_envs) (if already (array "" done_envs) (foldl (dlambda ((vs de) (k v)) (dlet (((x de) (recurse v de))) (array (concat vs (array (array k x))) de)))
|
||||
(array (array) done_envs)
|
||||
(slice e 0 -2))))
|
||||
((upper done_envs) (if already (array "" done_envs) (mif u (recurse u done_envs) (array "no_upper_likely_root_env" done_envs))))
|
||||
(done_envs (if already done_envs (cons index done_envs)))
|
||||
) (array (if already (true_str opening "omitted}")
|
||||
(if (> (len e) 30) (true_str "{" (len e) "env}")
|
||||
(true_str opening middle " upper: " upper "}"))) done_envs)
|
||||
))
|
||||
(true (error (true_str "some other str_strip? |" x "|")))
|
||||
)
|
||||
) (idx args -1) (array)) 0))))))
|
||||
|
||||
(true_str_strip str_strip)
|
||||
(str_strip (if speed_hack (lambda (& args) 0) str_strip))
|
||||
;(true_str_strip str_strip)
|
||||
(print_strip (lambda (& args) (println (lapply str_strip args))))
|
||||
|
||||
(env-lookup-helper (rec-lambda recurse (dict key i fail success) (cond ((and (= i (- (len dict) 1)) (= nil (idx dict i))) (fail))
|
||||
((= i (- (len dict) 1)) (recurse (.env_marked (idx dict i)) key 0 fail success))
|
||||
((= key (idx (idx dict i) 0)) (success (idx (idx dict i) 1)))
|
||||
(true (recurse dict key (+ i 1) fail success)))))
|
||||
(env-lookup (lambda (env key) (env-lookup-helper (.env_marked env) key 0 (lambda () (error (str key " not found in env " (str_strip env)))) (lambda (x) x))))
|
||||
|
||||
(strip (dlet ((helper (rec-lambda recurse (x need_value)
|
||||
(cond ((val? x) (.val x))
|
||||
((marked_array? x) (dlet ((stripped_values (map (lambda (x) (recurse x need_value)) (.marked_array_values x))))
|
||||
(mif (.marked_array_is_val x) stripped_values
|
||||
(error (str "needed value for this strip but got" x)))))
|
||||
((marked_symbol? x) (mif (.marked_symbol_is_val x) (.marked_symbol_value x)
|
||||
(error (str "needed value for this strip but got" x))))
|
||||
((comb? x) (error "got comb for strip, won't work"))
|
||||
((prim_comb? x) (idx x 2))
|
||||
; env emitting doesn't pay attention to real value right now, not sure mif that makes sense
|
||||
; TODO: properly handle de Bruijn indexed envs
|
||||
((marked_env? x) (error "got env for strip, won't work"))
|
||||
(true (error (str "some other strip? " x)))
|
||||
)
|
||||
))) (lambda (x) (dlet (
|
||||
;(_ (print_strip "stripping: " x))
|
||||
(r (helper x true))
|
||||
;(_ (println "result of strip " r))
|
||||
) r))))
|
||||
|
||||
(try_unval (rec-lambda recurse (x fail_f)
|
||||
(cond ((marked_array? x) (mif (not (.marked_array_is_val x)) (array false (fail_f x))
|
||||
(if (!= 0 (len (.marked_array_values x)))
|
||||
(dlet ((values (.marked_array_values x))
|
||||
((ok f) (recurse (idx values 0) fail_f))
|
||||
) (array ok (marked_array false false nil (cons f (slice values 1 -1)))))
|
||||
(array true (marked_array false false nil (array))))))
|
||||
((marked_symbol? x) (mif (.marked_symbol_is_val x) (array true (marked_symbol true (.marked_symbol_value x)))
|
||||
(array false (fail_f x))))
|
||||
(true (array true x))
|
||||
)
|
||||
))
|
||||
(try_unval_array (lambda (x) (foldl (dlambda ((ok a) x) (dlet (((nok p) (try_unval x (lambda (_) nil))))
|
||||
(array (and ok nok) (concat a (array p)))))
|
||||
(array true (array))
|
||||
x)))
|
||||
|
||||
(check_for_env_id_in_result (lambda (s_env_id x) (idx ((rec-lambda check_for_env_id_in_result (memo s_env_id x)
|
||||
(dlet (
|
||||
((need _hashes extra) (needed_for_progress x))
|
||||
(in_need (if (!= true need) (in_intset s_env_id need) false))
|
||||
(in_extra (in_intset s_env_id extra))
|
||||
) (cond ((or in_need in_extra) (array memo true))
|
||||
((!= true need) (array memo false))
|
||||
(true (dlet (
|
||||
|
||||
(old_way (dlet (
|
||||
(hash (.hash x))
|
||||
(result (if (marked_env? x) (get memo hash) false))
|
||||
) (if (array? result) (array memo (idx result 1)) (cond
|
||||
((marked_symbol? x) (array memo false))
|
||||
((marked_array? x) (dlet (
|
||||
(values (.marked_array_values x))
|
||||
((memo result) ((rec-lambda recurse (memo i) (if (= (len values) i) (array memo false)
|
||||
(dlet (((memo r) (check_for_env_id_in_result memo s_env_id (idx values i))))
|
||||
(if r (array memo true)
|
||||
(recurse memo (+ i 1))))))
|
||||
memo 0))
|
||||
) (array memo result)))
|
||||
((prim_comb? x) (array memo false))
|
||||
((val? x) (array memo false))
|
||||
((comb? x) (dlet (
|
||||
((wrap_level i_env_id de? se variadic params body) (.comb x))
|
||||
((memo in_se) (check_for_env_id_in_result memo s_env_id se))
|
||||
((memo total) (if (and (not in_se) (!= s_env_id i_env_id)) (check_for_env_id_in_result memo s_env_id body)
|
||||
(array memo in_se)))
|
||||
) (array memo total)))
|
||||
|
||||
((marked_env? x) (if (and (not (marked_env_real? x)) (= s_env_id (.marked_env_idx x))) (array memo true)
|
||||
(dlet (
|
||||
(values (slice (.env_marked x) 0 -2))
|
||||
(upper (idx (.env_marked x) -1))
|
||||
((memo result) ((rec-lambda recurse (memo i) (if (= (len values) i) (array memo false)
|
||||
(dlet (((memo r) (check_for_env_id_in_result memo s_env_id (idx (idx values i) 1))))
|
||||
(if r (array memo true)
|
||||
(recurse memo (+ i 1))))))
|
||||
memo 0))
|
||||
((memo result) (if (or result (= nil upper)) (array memo result)
|
||||
(check_for_env_id_in_result memo s_env_id upper)))
|
||||
(memo (put memo hash result))
|
||||
) (array memo result))))
|
||||
(true (error (str "Something odd passed to check_for_env_id_in_result " x)))
|
||||
))))
|
||||
|
||||
;(new_if_working (or in_need in_extra))
|
||||
;(_ (if (and (!= true need) (!= new_if_working (idx old_way 1))) (error "GAH looking for " s_env_id " - " need " - " extra " - " new_if_working " " (idx old_way 1))))
|
||||
) old_way))))) (array) s_env_id x) 1)))
|
||||
|
||||
(comb_takes_de? (lambda (x l) (cond
|
||||
((comb? x) (!= nil (.comb_des x)))
|
||||
((prim_comb? x) (cond ( (= (.prim_comb_sym x) 'vau) true)
|
||||
((and (= (.prim_comb_sym x) 'eval) (= 1 l)) true)
|
||||
((and (= (.prim_comb_sym x) 'veval) (= 1 l)) true)
|
||||
( (= (.prim_comb_sym x) 'lapply) true)
|
||||
( (= (.prim_comb_sym x) 'vapply) true)
|
||||
( (= (.prim_comb_sym x) 'cond) true) ; but not vcond
|
||||
(true false)))
|
||||
((and (marked_array? x) (not (.marked_array_is_val x))) true)
|
||||
((and (marked_symbol? x) (not (.marked_symbol_is_val x))) true)
|
||||
(true (error (str "illegal comb_takes_de? param " x)))
|
||||
)))
|
||||
|
||||
; Handles let 4.3 through macro level leaving it as (<comb wraplevel=1 (y) (+ y x 12)> 13)
|
||||
; need handling of symbols (which is illegal for eval but ok for calls) to push it farther
|
||||
(combiner_return_ok (rec-lambda combiner_return_ok (func_result env_id)
|
||||
(cond ((not (later_head? func_result)) (not (check_for_env_id_in_result env_id func_result)))
|
||||
; special cases now
|
||||
; *(veval body {env}) => (combiner_return_ok {env})
|
||||
; The reason we don't have to check body is that this form is only creatable in ways that body was origionally a value and only need {env}
|
||||
; Either it's created by eval, in which case it's fine, or it's created by something like (eval (array veval x de) de2) and the array has checked it,
|
||||
; or it's created via literal vau invocation, in which case the body is a value.
|
||||
((and (marked_array? func_result)
|
||||
(prim_comb? (idx (.marked_array_values func_result) 0))
|
||||
(= 'veval (.prim_comb_sym (idx (.marked_array_values func_result) 0)))
|
||||
(= 3 (len (.marked_array_values func_result)))
|
||||
(combiner_return_ok (idx (.marked_array_values func_result) 2) env_id)) true)
|
||||
; (func ...params) => (and (doesn't take de func) (foldl combiner_return_ok (cons func params)))
|
||||
;
|
||||
((and (marked_array? func_result)
|
||||
(not (comb_takes_de? (idx (.marked_array_values func_result) 0) (len (.marked_array_values func_result))))
|
||||
(foldl (lambda (a x) (and a (combiner_return_ok x env_id))) true (.marked_array_values func_result))) true)
|
||||
|
||||
; So that's enough for macro like, but we would like to take it farther
|
||||
; For like (let1 a 12 (wrap (vau (x) (let1 y (+ a 1) (+ y x a)))))
|
||||
; we get to (+ 13 x 12) not being a value, and it reconstructs
|
||||
; (<comb wraplevel=1 (y) (+ y x 12)> 13)
|
||||
; and that's what eval gets, and eval then gives up as well.
|
||||
|
||||
; That will get caught by the above cases to remain the expansion (<comb wraplevel=1 (y) (+ y x 12)> 13),
|
||||
; but ideally we really want another case to allow (+ 13 x 12) to bubble up
|
||||
; I think it would be covered by the (func ...params) case if a case is added to allow symbols to be bubbled up if their
|
||||
; needed for progress wasn't true or the current environment, BUT this doesn't work for eval, just for functions,
|
||||
; since eval changes the entire env chain (but that goes back to case 1, and might be eliminated at compile if it's an env reachable from the func).
|
||||
;
|
||||
;
|
||||
; Do note a key thing to be avoided is allowing any non-val inside a comb, since that can cause a fake env's ID to
|
||||
; reference the wrong env/comb in the chain.
|
||||
; We do allow calling eval with a fake env, but since it's only callable withbody value and is strict (by calling this)
|
||||
; about it's return conditions, and the env it's called with must be ok in the chain, and eval doesn't introduce a new scope, it works ok.
|
||||
; We do have to be careful about allowing returned later symbols from it though, since it could be an entirely different env chain.
|
||||
|
||||
(true false)
|
||||
)
|
||||
))
|
||||
|
||||
(drop_redundent_veval (rec-lambda drop_redundent_veval (partial_eval_helper x de env_stack pectx indent) (dlet (
|
||||
(env_id (.marked_env_idx de))
|
||||
(r (if
|
||||
(and (marked_array? x)
|
||||
(not (.marked_array_is_val x)))
|
||||
(if (and (prim_comb? (idx (.marked_array_values x) 0))
|
||||
(= 'veval (.prim_comb_sym (idx (.marked_array_values x) 0)))
|
||||
(= 3 (len (.marked_array_values x)))
|
||||
(not (marked_env_real? (idx (.marked_array_values x) 2)))
|
||||
(= env_id (.marked_env_idx (idx (.marked_array_values x) 2)))) (drop_redundent_veval partial_eval_helper (idx (.marked_array_values x) 1) de env_stack pectx (+ 1 indent))
|
||||
; wait, can it do this? will this mess with eval?
|
||||
|
||||
; basically making sure that this comb's params are still good to eval
|
||||
(if (and (or (prim_comb? (idx (.marked_array_values x) 0)) (comb? (idx (.marked_array_values x) 0)))
|
||||
(!= -1 (.any_comb_wrap_level (idx (.marked_array_values x) 0))))
|
||||
(dlet (((pectx err ress changed) (foldl (dlambda ((c er ds changed) p) (dlet (
|
||||
(pre_hash (.hash p))
|
||||
((c e d) (drop_redundent_veval partial_eval_helper p de env_stack c (+ 1 indent)))
|
||||
(err (mif er er e))
|
||||
(changed (mif err false (or (!= pre_hash (.hash d)) changed)))
|
||||
) (array c err (concat ds (array d)) changed)))
|
||||
(array pectx nil (array) false)
|
||||
(.marked_array_values x)))
|
||||
((pectx err new_array) (if (or (!= nil err) (not changed))
|
||||
(array pectx err x)
|
||||
(partial_eval_helper (marked_array false (.marked_array_is_attempted x) nil ress)
|
||||
false de env_stack pectx (+ indent 1) true)))
|
||||
|
||||
) (array pectx err new_array))
|
||||
(array pectx nil x))
|
||||
) (array pectx nil x))))
|
||||
|
||||
r)))
|
||||
|
||||
|
||||
(make_tmp_inner_env (lambda (params de? ue env_id)
|
||||
(dlet ((param_entries (map (lambda (p) (array p (marked_symbol env_id p))) params))
|
||||
(possible_de (mif (= nil de?) (array) (marked_symbol env_id de?)))
|
||||
) (marked_env false de? possible_de ue env_id param_entries))))
|
||||
|
||||
|
||||
(partial_eval_helper (rec-lambda partial_eval_helper (x only_head env env_stack pectx indent force)
|
||||
(dlet (((for_progress for_progress_hashes extra_env_ids) (needed_for_progress x))
|
||||
(_ (print_strip (indent_str indent) "for_progress " for_progress ", for_progress_hashes " for_progress_hashes " for " x))
|
||||
((env_counter memo) pectx)
|
||||
(hashes_now (foldl (lambda (a hash) (or a (= false (get-value-or-false memo hash)))) false for_progress_hashes))
|
||||
)
|
||||
(if (or force hashes_now (= for_progress true) (intset_intersection_nonempty for_progress (idx env_stack 0)))
|
||||
(cond ((val? x) (array pectx nil x))
|
||||
((marked_env? x) (dlet ((dbi (.marked_env_idx x)))
|
||||
; compiler calls with empty env stack
|
||||
(mif dbi (dlet ( (new_env ((rec-lambda rec (i len_env_stack) (cond ((= i len_env_stack) nil)
|
||||
((= dbi (.marked_env_idx (idx (idx env_stack 1) i))) (idx (idx env_stack 1) i))
|
||||
(true (rec (+ i 1) len_env_stack))))
|
||||
0 (len (idx env_stack 1))))
|
||||
(_ (println (str_strip "replacing " x) (str_strip " with (if nonnil) " new_env)))
|
||||
)
|
||||
(array pectx nil (if (!= nil new_env) new_env x)))
|
||||
(array pectx nil x))))
|
||||
|
||||
((comb? x) (dlet (((wrap_level env_id de? se variadic params body) (.comb x)))
|
||||
(mif (or (and (not (marked_env_real? env)) (not (marked_env_real? se))) ; both aren't real, re-evaluation of creation site
|
||||
(and (marked_env_real? env) (not (marked_env_real? se)))) ; new env real, but se isn't - creation!
|
||||
(dlet ((inner_env (make_tmp_inner_env params de? env env_id))
|
||||
((pectx err evaled_body) (partial_eval_helper body false inner_env (array (idx env_stack 0) (cons inner_env (idx env_stack 1))) pectx (+ indent 1) false)))
|
||||
(array pectx err (mif err nil (marked_comb wrap_level env_id de? env variadic params evaled_body))))
|
||||
(array pectx nil x))))
|
||||
((prim_comb? x) (array pectx nil x))
|
||||
((marked_symbol? x) (mif (.marked_symbol_is_val x) x
|
||||
(env-lookup-helper (.env_marked env) (.marked_symbol_value x) 0
|
||||
(lambda () (array pectx (str "could't find " (str_strip x) " in " (str_strip env)) nil))
|
||||
(lambda (x) (array pectx nil x)))))
|
||||
; Does this ever happen? non-fully-value arrays?
|
||||
((marked_array? x) (cond ((.marked_array_is_val x) (dlet ( ((pectx err inner_arr) (foldl (dlambda ((c er ds) p) (dlet (((c e d) (partial_eval_helper p false env env_stack c (+ 1 indent) false))) (array c (mif er er e) (concat ds (array d)))))
|
||||
(array pectx nil (array))
|
||||
(.marked_array_values x)))
|
||||
) (array pectx err (mif err nil (marked_array true false nil inner_arr)))))
|
||||
((= 0 (len (.marked_array_values x))) (array pectx "Partial eval on empty array" nil))
|
||||
(true (dlet ((values (.marked_array_values x))
|
||||
(_ (print_strip (indent_str indent) "partial_evaling comb " (idx values 0)))
|
||||
|
||||
(literal_params (slice values 1 -1))
|
||||
((pectx err comb) (partial_eval_helper (idx values 0) true env env_stack pectx (+ 1 indent) false))
|
||||
) (cond ((!= nil err) (array pectx err nil))
|
||||
((later_head? comb) (array pectx nil (marked_array false true nil (cons comb literal_params))))
|
||||
((not (or (comb? comb) (prim_comb? comb))) (array pectx (str "impossible comb value " x) nil))
|
||||
(true (dlet (
|
||||
; If we haven't evaluated the function before at all, we would like to partially evaluate it so we know
|
||||
; what it needs. We'll see if this re-introduces exponentail (I think this should limit it to twice?)
|
||||
((pectx comb_err comb) (if (and (= nil err) (= true (needed_for_progress_slim comb)))
|
||||
(partial_eval_helper comb false env env_stack pectx (+ 1 indent) false)
|
||||
(array pectx err comb)))
|
||||
(_ (println (indent_str indent) "Going to do an array call!"))
|
||||
(indent (+ 1 indent))
|
||||
(_ (print_strip (indent_str indent) "total (in env " (.marked_env_idx env) ") is (proceeding err " err ") " x))
|
||||
(map_rp_eval (lambda (pectx ps) (foldl (dlambda ((c er ds) p) (dlet ((_ (print_strip (indent_str indent) "rp_evaling " p)) ((c e d) (partial_eval_helper p false env env_stack c (+ 1 indent) false)) (_ (print_strip (indent_str indent) "result of rp_eval was err " e " and value " d))) (array c (mif er er e) (concat ds (array d)))))
|
||||
(array pectx nil (array))
|
||||
ps)))
|
||||
(wrap_level (.any_comb_wrap_level comb))
|
||||
; -1 is a minor hack for veval to prevent re-eval
|
||||
; in the wrong env and vcond to prevent guarded
|
||||
; infinate recursion
|
||||
((remaining_wrap param_err evaled_params pectx) (if (= -1 wrap_level)
|
||||
(array -1 nil literal_params pectx)
|
||||
((rec-lambda param-recurse (wrap cparams pectx)
|
||||
(dlet (
|
||||
(_ (print (indent_str indent) "For initial rp_eval:"))
|
||||
(_ (map (lambda (x) (print_strip (indent_str indent) "item " x)) cparams))
|
||||
((pectx er pre_evaled) (map_rp_eval pectx cparams))
|
||||
(_ (print (indent_str indent) "er for intial rp_eval: " er))
|
||||
)
|
||||
(mif er (array wrap er nil pectx)
|
||||
(mif (!= 0 wrap)
|
||||
(dlet (((ok unval_params) (try_unval_array pre_evaled)))
|
||||
(mif (not ok) (array wrap nil pre_evaled pectx)
|
||||
(param-recurse (- wrap 1) unval_params pectx)))
|
||||
(array wrap nil pre_evaled pectx)))))
|
||||
wrap_level literal_params pectx)))
|
||||
(_ (println (indent_str indent) "Done evaluating parameters"))
|
||||
|
||||
(l_later_call_array (lambda () (marked_array false true nil (cons (with_wrap_level comb remaining_wrap) evaled_params))))
|
||||
(ok_and_non_later (or (= -1 remaining_wrap)
|
||||
(and (= 0 remaining_wrap) (if (and (prim_comb? comb) (.prim_comb_val_head_ok comb))
|
||||
(is_all_head_values evaled_params)
|
||||
(is_all_values evaled_params)))))
|
||||
(_ (println (indent_str indent) "ok_and_non_later " ok_and_non_later))
|
||||
) (cond ((!= nil comb_err) (array pectx comb_err nil))
|
||||
((!= nil param_err) (array pectx param_err nil))
|
||||
((not ok_and_non_later) (array pectx nil (l_later_call_array)))
|
||||
((prim_comb? comb) (dlet (
|
||||
(_ (println (indent_str indent) "Calling prim comb " (.prim_comb_sym comb)))
|
||||
((pectx err result) ((.prim_comb_handler comb) only_head env env_stack pectx evaled_params (+ 1 indent)))
|
||||
) (if (= 'LATER err) (array pectx nil (l_later_call_array))
|
||||
(array pectx err result))))
|
||||
((comb? comb) (dlet (
|
||||
((wrap_level env_id de? se variadic params body) (.comb comb))
|
||||
|
||||
|
||||
(final_params (mif variadic (concat (slice evaled_params 0 (- (len params) 1))
|
||||
(array (marked_array true false nil (slice evaled_params (- (len params) 1) -1))))
|
||||
evaled_params))
|
||||
(de_env (mif (!= nil de?) env nil))
|
||||
(inner_env (marked_env true de? de_env se env_id (zip params final_params)))
|
||||
(_ (print_strip (indent_str indent) " with inner_env is " inner_env))
|
||||
(_ (print_strip (indent_str indent) "going to eval " body))
|
||||
|
||||
; prevent infinite recursion
|
||||
(hash (combine_hash (.hash body) (.hash inner_env)))
|
||||
((env_counter memo) pectx)
|
||||
((pectx func_err func_result rec_stop) (if (!= false (get-value-or-false memo hash))
|
||||
(array pectx nil "stopping for infinite recursion" true)
|
||||
(dlet (
|
||||
(new_memo (put memo hash nil))
|
||||
(pectx (array env_counter new_memo))
|
||||
((pectx func_err func_result) (partial_eval_helper body only_head inner_env
|
||||
(array (intset_item_union (idx env_stack 0) env_id)
|
||||
(cons inner_env (idx env_stack 1)))
|
||||
pectx (+ 1 indent) false))
|
||||
((env_counter new_memo) pectx)
|
||||
(pectx (array env_counter memo))
|
||||
) (array pectx func_err func_result false))))
|
||||
|
||||
(_ (print_strip (indent_str indent) "evaled result of function call (in env " (.marked_env_idx env) ", with inner " env_id ") and err " func_err " is " func_result))
|
||||
(must_stop_maybe_id (and (= nil func_err)
|
||||
(or rec_stop (if (not (combiner_return_ok func_result env_id))
|
||||
(if (!= nil de?) (.marked_env_idx env) true)
|
||||
false))))
|
||||
) (if (!= nil func_err) (array pectx func_err nil)
|
||||
(if must_stop_maybe_id
|
||||
(array pectx nil (marked_array false must_stop_maybe_id (if rec_stop (array hash) nil) (cons (with_wrap_level comb remaining_wrap) evaled_params)))
|
||||
(drop_redundent_veval partial_eval_helper func_result env env_stack pectx indent)))))
|
||||
)))
|
||||
)))))
|
||||
|
||||
(true (array pectx (str "impossible partial_eval value " x) nil))
|
||||
)
|
||||
; otherwise, we can't make progress yet
|
||||
(drop_redundent_veval partial_eval_helper x env env_stack pectx indent)))
|
||||
))
|
||||
|
||||
(needs_params_val_lambda (lambda (f_sym actual_function) (dlet (
|
||||
(handler (rec-lambda recurse (only_head de env_stack pectx params indent)
|
||||
(array pectx nil (mark false (lapply actual_function (map strip params))))))
|
||||
) (array f_sym (marked_prim_comb handler f_sym 1 false)))))
|
||||
|
||||
(give_up_eval_params (lambda (f_sym actual_function) (dlet (
|
||||
(handler (lambda (only_head de env_stack pectx params indent) (array pectx 'LATER nil)))
|
||||
) (array f_sym (marked_prim_comb handler f_sym 1 false)))))
|
||||
|
||||
(veval_inner (rec-lambda recurse (only_head de env_stack pectx params indent) (dlet (
|
||||
(body (idx params 0))
|
||||
(implicit_env (!= 2 (len params)))
|
||||
(eval_env (if implicit_env de (idx params 1)))
|
||||
((pectx err eval_env) (if implicit_env (array pectx nil de)
|
||||
(partial_eval_helper (idx params 1) only_head de env_stack pectx (+ 1 indent) false)))
|
||||
((pectx err ebody) (if (or (!= nil err) (not (marked_env? eval_env)))
|
||||
(array pectx err body)
|
||||
(partial_eval_helper body only_head eval_env env_stack pectx (+ 1 indent) false)))
|
||||
) (cond
|
||||
((!= nil err) (array pectx err nil))
|
||||
; If our env was implicit, then our unval'd code can be inlined directly in our caller
|
||||
(implicit_env (drop_redundent_veval partial_eval_helper ebody de env_stack pectx indent))
|
||||
((combiner_return_ok ebody (.marked_env_idx eval_env)) (drop_redundent_veval partial_eval_helper ebody de env_stack pectx indent))
|
||||
(true (drop_redundent_veval partial_eval_helper (marked_array false true nil (array
|
||||
(marked_prim_comb recurse 'veval -1 true)
|
||||
ebody
|
||||
eval_env
|
||||
))
|
||||
de env_stack pectx indent))
|
||||
))))
|
||||
|
||||
|
||||
(root_marked_env (marked_env true nil nil nil nil (array
|
||||
|
||||
(array 'eval (marked_prim_comb (rec-lambda recurse (only_head de env_stack pectx evaled_params indent)
|
||||
(if (not (total_value? (idx evaled_params 0))) (array pectx nil (marked_array false true nil (cons (marked_prim_comb recurse 'eval 0 true) evaled_params)))
|
||||
(if (and (= 2 (len evaled_params)) (not (marked_env? (idx evaled_params 1)))) (array pectx nil (marked_array false true nil (cons (marked_prim_comb recurse 'eval 0 true) evaled_params)))
|
||||
(dlet (
|
||||
(body (idx evaled_params 0))
|
||||
(implicit_env (!= 2 (len evaled_params)))
|
||||
(eval_env (if implicit_env de (idx evaled_params 1)))
|
||||
((ok unval_body) (try_unval body (lambda (_) nil)))
|
||||
(_ (if (not ok) (error "actually impossible eval unval")))
|
||||
) (veval_inner only_head de env_stack pectx (if implicit_env (array unval_body) (array unval_body eval_env)) indent))))
|
||||
) 'eval 1 true))
|
||||
|
||||
(array 'vapply (marked_prim_comb (dlambda (only_head de env_stack pectx (f ps ide) indent)
|
||||
(veval_inner only_head de env_stack pectx (array (marked_array false false nil (cons f (.marked_array_values ps))) ide) (+ 1 indent))
|
||||
) 'vapply 1 true))
|
||||
(array 'lapply (marked_prim_comb (dlambda (only_head de env_stack pectx (f ps) indent)
|
||||
(veval_inner only_head de env_stack pectx (array (marked_array false false nil (cons (with_wrap_level f (- (.any_comb_wrap_level f) 1)) (.marked_array_values ps)))) (+ 1 indent))
|
||||
) 'lapply 1 true))
|
||||
|
||||
(array 'vau (marked_prim_comb (lambda (only_head de env_stack pectx params indent) (dlet (
|
||||
(mde? (mif (= 3 (len params)) (idx params 0) nil))
|
||||
(vau_mde? (mif (= nil mde?) (array) (array mde?)))
|
||||
(_ (print (indent_str indent) "mde? is " mde?))
|
||||
(_ (print (indent_str indent) "\tmde? if " (mif mde? #t #f)))
|
||||
(de? (mif mde? (.marked_symbol_value mde?) nil))
|
||||
(_ (print (indent_str indent) "de? is " de?))
|
||||
(vau_de? (mif (= nil de?) (array) (array de?)))
|
||||
(raw_marked_params (mif (= nil de?) (idx params 0) (idx params 1)))
|
||||
(raw_params (map (lambda (x) (mif (not (marked_symbol? x)) (error (str "not a marked symbol " x))
|
||||
(.marked_symbol_value x))) (.marked_array_values raw_marked_params)))
|
||||
|
||||
((variadic vau_params) (foldl (dlambda ((v a) x) (mif (= x '&) (array true a) (array v (concat a (array x))))) (array false (array)) raw_params))
|
||||
((ok body) (try_unval (mif (= nil de?) (idx params 1) (idx params 2)) (lambda (_) nil)))
|
||||
(_ (if (not ok) (error "actually impossible vau unval")))
|
||||
((env_counter memo) pectx)
|
||||
(new_id env_counter)
|
||||
(env_counter (+ 1 env_counter))
|
||||
(pectx (array env_counter memo))
|
||||
((pectx err pe_body) (if only_head (array pectx nil body)
|
||||
(dlet (
|
||||
(inner_env (make_tmp_inner_env vau_params de? de new_id))
|
||||
(_ (print_strip (indent_str indent) "in vau, evaluating body with 'later params - " body))
|
||||
((pectx err pe_body) (partial_eval_helper body false inner_env (array (idx env_stack 0)
|
||||
(cons inner_env (idx env_stack 1))) pectx (+ 1 indent) false))
|
||||
(_ (print_strip (indent_str indent) "in vau, result of evaluating body was " pe_body))
|
||||
) (array pectx err pe_body))))
|
||||
) (mif err (array pectx err nil) (array pectx nil (marked_comb 0 new_id de? de variadic vau_params pe_body)))
|
||||
)) 'vau 0 true))
|
||||
|
||||
|
||||
|
||||
|
||||
(array 'empty_env (marked_env true nil nil nil nil nil))
|
||||
)))
|
||||
|
||||
|
||||
|
||||
|
||||
; This causes ?infinate? recursion, doesn't happen if "if" is replaced with cond
|
||||
;(test_func (vau (x) (if x (COMICAL 0) 0)))
|
||||
|
||||
|
||||
;(and_fold (foldl and true '(true true false true)))
|
||||
;(monad (array 'write 1 (str "Hello from compiled code! " and_fold " here's a hashed string " (hash_string "hia") "\n") (vau (written code) (array 'exit 0))))
|
||||
;(monad (array 'write 1 (str "Hello from compiled code! " (mif nil 1 2) " " (mif 1 3 4) "\n") (vau (written code) (array 'exit 0))))
|
||||
(monad (array 'write 1 (str "Hello from compiled code! " "\n") (vau (written code) (array 'exit (if (not written) 1)))))
|
||||
|
||||
) monad)
|
||||
)
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
; this would be the macro style version (((
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
;)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de)) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
6946
partial_eval.scm
902
sl/Cargo.lock
generated
Normal file
@@ -0,0 +1,902 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
|
||||
dependencies = [
|
||||
"term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4fdf311b2564edbf43d3a06335d309814f6ec60f55d090885d68e1a2e664c04"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-frontend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b5bb9245ec7dcc04d03110e538d31f0969d301c9d673145f4b4d5c3478539a3"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebb18d10e5ddac43ba4ca8fd4e310938569c3e484cc01b6372b27dc5bb4dfd28"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-control",
|
||||
"cranelift-entity",
|
||||
"cranelift-isle",
|
||||
"gimli",
|
||||
"hashbrown 0.14.2",
|
||||
"log",
|
||||
"regalloc2",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a3ce6d22982c1b9b6b012654258bab1a13947bb12703518bef06b1a4867c3d6"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47220fd4f9a0ce23541652b6f16f83868d282602c600d14934b2a4c166b4bd80"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed5a4c42672aea9b6e820046b52e47a1c05d3394a6cdf4cb3c3c4b702f954bd2"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b4e9a3296fc827f9d35135dc2c0c8dd8d8359eb1ef904bae2d55d5bcb0c9f94"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ec537d0f0b8e084517f3e7bfa1d89af343d7c7df455573fca9f272d4e01267"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45bab6d69919d210a50331d35cc6ce111567bc040aebac63a8ae130d0400a075"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1daca8224e77263494e1d949daeb0a0a0992f9c489d4dc395bfc8ddda0eafcaf"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-control",
|
||||
"cranelift-entity",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"libc",
|
||||
"log",
|
||||
"region",
|
||||
"target-lexicon",
|
||||
"wasmtime-jit-icache-coherence",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533ebbad90a77980bdbbe6bd4beee9598a74db06316e8a9def7a6d9564e19f5e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-control",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.101.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f32e81605f352cf37af5463f11cd7deec7b6572741931a8d372f7fdd4a744f5d"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"ena",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"pico-args",
|
||||
"regex",
|
||||
"regex-syntax 0.7.5",
|
||||
"string_cache",
|
||||
"term",
|
||||
"tiny-keccak",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "new_debug_unreachable"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
"rustc-hash",
|
||||
"slice-group-by",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "region"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
"mach",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "sl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift",
|
||||
"cranelift-jit",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slice-group-by"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
"rustversion",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "14.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f67e6be36375c39cff57ed3b137ab691afbf2d9ba8ee1c01f77888413f218749"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
22
sl/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "sl"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# 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.20", features=["lexer"]}
|
||||
regex = "1"
|
||||
once_cell = "1"
|
||||
anyhow = "1"
|
||||
cranelift = "0.101.4"
|
||||
cranelift-module = "0.101.4"
|
||||
cranelift-jit = "0.101.4"
|
||||
cranelift-native = "0.101.4"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.20"
|
||||
5
sl/build.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
extern crate lalrpop;
|
||||
|
||||
fn main() {
|
||||
lalrpop::process_root().unwrap();
|
||||
}
|
||||
32
sl/src/grammar.lalrpop
Normal file
@@ -0,0 +1,32 @@
|
||||
use std::str::FromStr;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use sl::Form;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Term: Rc<Form> = {
|
||||
NUM => Rc::new(Form::Int(i32::from_str(<>).unwrap())),
|
||||
SYM => Rc::new(Form::Symbol(<>.to_owned(),RefCell::new(None))),
|
||||
"(" <ListInside?> ")" => <>.unwrap_or(Rc::new(Form::Nil)),
|
||||
"'" <Term> => Rc::new(Form::Pair(Rc::new(Form::Symbol("quote".to_owned(),RefCell::new(None))), Rc::new(Form::Pair(<>, Rc::new(Form::Nil),RefCell::new(None))),RefCell::new(None))),
|
||||
"!" <h: Term> <t: Term> => {
|
||||
h.append(t).unwrap()
|
||||
},
|
||||
};
|
||||
ListInside: Rc<Form> = {
|
||||
<Term> => Rc::new(Form::Pair(<>, Rc::new(Form::Nil),RefCell::new(None))),
|
||||
<h: Term> <t: ListInside> => Rc::new(Form::Pair(h, t,RefCell::new(None))),
|
||||
<a: Term> "." <d: Term> => Rc::new(Form::Pair(a, d,RefCell::new(None))),
|
||||
}
|
||||
match {
|
||||
"(",
|
||||
")",
|
||||
".",
|
||||
"'",
|
||||
"!",
|
||||
r"[0-9]+" => NUM,
|
||||
r"[a-zA-Z+*/_=?%&|^<>-][\w+*/=_?%&|^<>-]*" => SYM,
|
||||
r"(;[^\n]*\n)|\s+" => { }
|
||||
}
|
||||
|
||||
614
sl/src/lib.rs
Normal file
@@ -0,0 +1,614 @@
|
||||
use std::rc::Rc;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use anyhow::{anyhow,bail,Result};
|
||||
|
||||
|
||||
// This first Simple Lisp really is
|
||||
//
|
||||
// No fexprs, no mutation, no continuations, no macros, no strings.
|
||||
// Int/Bool/Nil/Pair/Symbol/Closure/Prim.
|
||||
//
|
||||
// Figuring out GC between a JIT and Rust will be tricky.
|
||||
// Can start with a like tracing-JIT-into-bytecode
|
||||
// Replcing Env with pairs or somesuch would make JIT interop easier I think, because we wouldn't
|
||||
// have to deal with refcell, but then we would again for mutation.
|
||||
// Maybe doing all allocation on the Rust side with #[no_mangle] functions would make things easier
|
||||
// mmmm no let's make our own Box, Rc, maybe Arc
|
||||
// rustonomicon
|
||||
|
||||
// What if we're cute and use the ID
|
||||
// like we will eventually use value tagging
|
||||
// like, use the same encoding
|
||||
// interned symbols and all
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
|
||||
pub struct ID {
|
||||
id: i64
|
||||
}
|
||||
impl fmt::Display for ID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Form {
|
||||
Nil,
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
Symbol(String, RefCell<Option<ID>>),
|
||||
Pair(Rc<Form>, Rc<Form>, RefCell<Option<ID>>),
|
||||
Closure(Vec<String>, Rc<RefCell<Env>>, Rc<Form>, ID),
|
||||
Prim(Prim),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum Prim {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Eq,
|
||||
Cons,
|
||||
Car,
|
||||
Cdr,
|
||||
}
|
||||
|
||||
impl Form {
|
||||
fn my_eq(&self, o: &Rc<Form>) -> bool {
|
||||
match self {
|
||||
Form::Nil => o.is_nil(),
|
||||
Form::Int(i) => if let Ok(oi) = o.int() { *i == oi } else { false },
|
||||
Form::Bool(b) => if let Ok(ob) = o.bool() { *b == ob } else { false },
|
||||
Form::Symbol(s, _id) => if let Ok(os) = o.sym() { s == os } else { false },
|
||||
Form::Pair(a,b,_id) => if let Ok((oa,ob)) = o.pair() { a.my_eq(&oa) && b.my_eq(&ob) } else { false },
|
||||
Form::Closure(_, _, _, _) => false,
|
||||
Form::Prim(p) => match &**o { Form::Prim(op) => p == op, _ => false },
|
||||
}
|
||||
}
|
||||
fn new_pair(car: Rc<Form>, cdr: Rc<Form>) -> Rc<Form> {
|
||||
Rc::new(Form::Pair(car, cdr, RefCell::new(None)))
|
||||
}
|
||||
fn new_nil() -> Rc<Form> {
|
||||
Rc::new(Form::Nil)
|
||||
}
|
||||
fn new_int(i: i32) -> Rc<Form> {
|
||||
Rc::new(Form::Int(i))
|
||||
}
|
||||
fn new_bool(b: bool) -> Rc<Form> {
|
||||
Rc::new(Form::Bool(b))
|
||||
}
|
||||
fn new_closure(params: Vec<String>, env: Rc<RefCell<Env>>, body: Rc<Form>, ctx: &mut Ctx) -> Rc<Form> {
|
||||
Rc::new(Form::Closure(params, env, body, ctx.alloc_id()))
|
||||
}
|
||||
fn truthy(&self) -> bool {
|
||||
match self {
|
||||
Form::Bool(b) => *b,
|
||||
Form::Nil => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
fn bool(&self) -> Result<bool> {
|
||||
match self {
|
||||
Form::Bool(b) => Ok(*b),
|
||||
_ => Err(anyhow!("bool on not a bool")),
|
||||
}
|
||||
}
|
||||
fn int(&self) -> Result<i32> {
|
||||
match self {
|
||||
Form::Int(i) => Ok(*i),
|
||||
_ => Err(anyhow!("int on not a int")),
|
||||
}
|
||||
}
|
||||
fn prim(&self) -> Result<Prim> {
|
||||
match self {
|
||||
Form::Prim(p) => Ok(*p),
|
||||
_ => Err(anyhow!("prim on not a prim")),
|
||||
}
|
||||
}
|
||||
fn sym(&self) -> Result<&str> {
|
||||
match self {
|
||||
Form::Symbol(s, _id) => Ok(s),
|
||||
_ => Err(anyhow!("sym on not a sym")),
|
||||
}
|
||||
}
|
||||
fn pair(&self) -> Result<(Rc<Form>,Rc<Form>)> {
|
||||
match self {
|
||||
Form::Pair(car, cdr, _id) => Ok((Rc::clone(car),Rc::clone(cdr))),
|
||||
_ => Err(anyhow!("pair on not a pair")),
|
||||
}
|
||||
}
|
||||
fn car(&self) -> Result<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, _cdr, _id) => Ok(Rc::clone(car)),
|
||||
_ => Err(anyhow!("car on not a pair")),
|
||||
}
|
||||
}
|
||||
fn cdr(&self) -> Result<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(_car, cdr, _id) => Ok(Rc::clone(cdr)),
|
||||
_ => Err(anyhow!("cdr on not a pair")),
|
||||
}
|
||||
}
|
||||
fn is_nil(&self) -> bool {
|
||||
match self {
|
||||
Form::Nil => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn append(&self, x: Rc<Form>) -> Result<Rc<Form>> {
|
||||
match self {
|
||||
Form::Pair(car, cdr, _id) => cdr.append(x).map(|x| Rc::new(Form::Pair(Rc::clone(car), x, RefCell::new(None)))),
|
||||
Form::Nil => Ok(Rc::new(Form::Pair(x, Rc::new(Form::Nil), RefCell::new(None)))),
|
||||
_ => Err(anyhow!("append to not a pair")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Env {
|
||||
u: Option<Rc<RefCell<Env>>>,
|
||||
// split this into
|
||||
// BTreeMap<String, usize>
|
||||
// Vec<usize> so that traced code can refer by index
|
||||
m: BTreeMap<String, Rc<Form>>
|
||||
}
|
||||
impl Env {
|
||||
pub fn root_env() -> Rc<RefCell<Env>> {
|
||||
Rc::new(RefCell::new(Env {
|
||||
u: None,
|
||||
m: [
|
||||
("+", Rc::new(Form::Prim(Prim::Add))),
|
||||
("-", Rc::new(Form::Prim(Prim::Sub))),
|
||||
("*", Rc::new(Form::Prim(Prim::Mul))),
|
||||
("/", Rc::new(Form::Prim(Prim::Div))),
|
||||
("%", Rc::new(Form::Prim(Prim::Mod))),
|
||||
("cons", Rc::new(Form::Prim(Prim::Cons))),
|
||||
("cdr", Rc::new(Form::Prim(Prim::Cdr))),
|
||||
("car", Rc::new(Form::Prim(Prim::Car))),
|
||||
("=", Rc::new(Form::Prim(Prim::Eq))),
|
||||
("nil", Form::new_nil()),
|
||||
].into_iter().map(|(s,p)| (s.to_owned(), p)).collect()
|
||||
}))
|
||||
}
|
||||
pub fn chain(o: &Rc<RefCell<Env>>) -> Rc<RefCell<Env>> {
|
||||
Rc::new(RefCell::new(Env {
|
||||
u: Some(Rc::clone(o)),
|
||||
m: BTreeMap::new(),
|
||||
}))
|
||||
}
|
||||
pub fn lookup(&self, s: &str) -> Result<Rc<Form>> {
|
||||
if let Some(r) = self.m.get(s) {
|
||||
Ok(Rc::clone(r))
|
||||
} else if let Some(u) = &self.u {
|
||||
u.borrow().lookup(s)
|
||||
} else {
|
||||
bail!("lookup of {s} failed")
|
||||
}
|
||||
}
|
||||
pub fn define(&mut self, s: String, v: Rc<Form>) {
|
||||
// no mutation, shadowing in inner scope ok
|
||||
assert!(!self.m.contains_key(&s));
|
||||
self.m.insert(s, v);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Op {
|
||||
Guard { const_value: Rc<Form>, side: (Option<Rc<Form>>, Rc<Cont>) },
|
||||
Debug,
|
||||
Define { sym: String },
|
||||
}
|
||||
impl fmt::Display for Op {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Op::Guard { const_value, side } => write!(f, "Guard"),
|
||||
Op::Debug => write!(f, "Debug"),
|
||||
Op::Define { sym } => write!(f, "Define {sym}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Trace {
|
||||
id: ID,
|
||||
// needs to track which are constants
|
||||
ops: Vec<Op>,
|
||||
}
|
||||
impl Trace {
|
||||
fn new(id: ID) -> Self {
|
||||
Trace { id, ops: vec![] }
|
||||
}
|
||||
}
|
||||
impl fmt::Display for Trace {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Trace for {} [", self.id)?;
|
||||
for op in &self.ops {
|
||||
write!(f, " {}", op)?;
|
||||
}
|
||||
write!(f, " ]")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Ctx {
|
||||
id_counter: i64,
|
||||
func_calls: BTreeMap<ID, i64>,
|
||||
tracing: Option<Trace>,
|
||||
traces: BTreeMap<ID, Trace>,
|
||||
}
|
||||
impl fmt::Display for Ctx {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Ctx")
|
||||
}
|
||||
}
|
||||
impl Ctx {
|
||||
fn new() -> Ctx {
|
||||
Ctx {
|
||||
id_counter: 0,
|
||||
func_calls: BTreeMap::new(),
|
||||
tracing: None,
|
||||
traces: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
fn alloc_id(&mut self) -> ID {
|
||||
self.id_counter += 1;
|
||||
ID { id: self.id_counter }
|
||||
}
|
||||
fn trace_running(&self) -> bool { self.tracing.is_some() }
|
||||
fn trace_call_start(&mut self, id: ID) {
|
||||
|
||||
// Needs to take and use parameters for mid-trace
|
||||
// needs to guard on function called if non-constant
|
||||
|
||||
let entry = self.func_calls.entry(id).or_insert(0);
|
||||
println!("tracing call start for {id}, has been called {} times so far", *entry);
|
||||
*entry += 1;
|
||||
if let Some(trace) = &self.tracing {
|
||||
if trace.id == id {
|
||||
println!("Ending trace at recursive call!");
|
||||
println!("\t{}", trace);
|
||||
self.traces.insert(id, self.tracing.take().unwrap());
|
||||
}
|
||||
} else if *entry > 1 && self.traces.get(&id).is_none() {
|
||||
self.tracing = Some(Trace::new(id));
|
||||
}
|
||||
}
|
||||
fn trace_call_end(&mut self, id: ID) {
|
||||
// associate with it or something
|
||||
println!("tracing call end for {id}");
|
||||
if let Some(trace) = &self.tracing {
|
||||
if trace.id == id {
|
||||
println!("Ending trace at end of call!");
|
||||
println!("\t{}", trace);
|
||||
self.traces.insert(id, self.tracing.take().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
fn trace_guard<T: Into<Form> + std::fmt::Debug >(&mut self, value: T, other: impl Fn()->(Option<Rc<Form>>,Rc<Cont>)) {
|
||||
println!("Tracing guard {value:?}");
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
trace.ops.push(Op::Guard { const_value: Rc::new(value.into()), side: other() });
|
||||
}
|
||||
}
|
||||
fn trace_debug(&mut self) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
trace.ops.push(Op::Debug);
|
||||
}
|
||||
}
|
||||
fn trace_define(&mut self, sym: &str) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
trace.ops.push(Op::Define { sym: sym.to_owned() });
|
||||
}
|
||||
}
|
||||
fn trace_call_bit(&mut self) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
// Trace call start, of course, handles the other side!
|
||||
// Though I guess that means call start should recieve the parameters
|
||||
// also, for like variables, it should guard on what function
|
||||
// if dynamic, interacts with the constant tracking
|
||||
fn trace_prim(&mut self, p: &Prim) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
fn trace_lookup(&mut self, s: &str) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
fn trace_constant(&mut self, c: &Rc<Form>) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
fn trace_lambda(&mut self, params: &[String], e: &Rc<RefCell<Env>>, body: &Rc<Form>) {
|
||||
if let Some(trace) = &mut self.tracing {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone,Debug)]
|
||||
enum Cont {
|
||||
MetaRet,
|
||||
Ret { e: Rc<RefCell<Env>>, id: ID, c: Rc<Cont> },
|
||||
Eval { c: Rc<Cont> },
|
||||
Prim { s: &'static str, to_go: Rc<Form>, c: Rc<Cont> },
|
||||
Call { evaled: Vec<Rc<Form>>, to_go: Rc<Form>, c: Rc<Cont> },
|
||||
}
|
||||
|
||||
pub fn eval(f: Rc<Form>) -> Result<Rc<Form>> {
|
||||
let mut ctx = Ctx::new();
|
||||
let mut f = f;
|
||||
let mut e = Env::root_env();
|
||||
let mut c = Cont::Eval { c: Rc::new(Cont::MetaRet) };
|
||||
|
||||
loop {
|
||||
match c {
|
||||
Cont::MetaRet => {
|
||||
println!("Ctx was {ctx}");
|
||||
assert!(!ctx.trace_running());
|
||||
return Ok(f);
|
||||
}
|
||||
Cont::Ret { e: ne, id, c: nc } => {
|
||||
ctx.trace_call_end(id);
|
||||
e = ne;
|
||||
c = (*nc).clone();
|
||||
},
|
||||
Cont::Prim { s, to_go, c: nc } => {
|
||||
match s {
|
||||
"if" => {
|
||||
let thn = to_go.car()?;
|
||||
let els = to_go.cdr()?.car()?;
|
||||
if f.truthy() {
|
||||
ctx.trace_guard(true, || (Some(Rc::clone(&els)), Rc::new(Cont::Eval { c: Rc::clone(&nc) })));
|
||||
f = thn;
|
||||
} else {
|
||||
ctx.trace_guard(false, ||(Some(Rc::clone(&thn)), Rc::new(Cont::Eval { c: Rc::clone(&nc) })));
|
||||
f = els;
|
||||
}
|
||||
c = Cont::Eval { c: nc };
|
||||
},
|
||||
"or" => {
|
||||
let other = to_go.car()?;
|
||||
if !f.truthy() {
|
||||
ctx.trace_guard(false, || (None, nc.clone()));
|
||||
f = other;
|
||||
c = Cont::Eval { c: nc };
|
||||
} else {
|
||||
ctx.trace_guard(true, || (Some(Rc::clone(&other)), Rc::new(Cont::Eval { c: Rc::clone(&nc) })));
|
||||
c = (*nc).clone();
|
||||
}
|
||||
},
|
||||
"and" => {
|
||||
let other = to_go.car()?;
|
||||
if f.truthy() {
|
||||
ctx.trace_guard(true, || (None, nc.clone()));
|
||||
f = other;
|
||||
c = Cont::Eval { c: nc };
|
||||
} else {
|
||||
ctx.trace_guard(false, || (Some(Rc::clone(&other)), Rc::new(Cont::Eval { c: Rc::clone(&nc) })));
|
||||
c = (*nc).clone();
|
||||
}
|
||||
},
|
||||
"begin" => {
|
||||
if to_go.is_nil() {
|
||||
c = (*nc).clone();
|
||||
} else {
|
||||
f = to_go.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "begin", to_go: to_go.cdr()?, c: nc }) };
|
||||
}
|
||||
},
|
||||
"debug" => {
|
||||
println!("Debug: {f}");
|
||||
ctx.trace_debug();
|
||||
c = (*nc).clone();
|
||||
},
|
||||
"define" => {
|
||||
let sym = to_go.sym()?.to_string();
|
||||
ctx.trace_define(&sym);
|
||||
e.borrow_mut().define(sym, Rc::clone(&f));
|
||||
c = (*nc).clone();
|
||||
},
|
||||
_ => {
|
||||
panic!("bad prim {s}");
|
||||
}
|
||||
}
|
||||
},
|
||||
Cont::Call { mut evaled, to_go, c: nc } => {
|
||||
ctx.trace_call_bit();
|
||||
evaled.push(f);
|
||||
if to_go.is_nil() {
|
||||
// do call
|
||||
let arg_len = evaled.len() - 1;
|
||||
let mut evaled_iter = evaled.into_iter();
|
||||
let comb = evaled_iter.next().unwrap();
|
||||
match &*comb {
|
||||
Form::Closure(ps, ie, b, id) => {
|
||||
if ps.len() != arg_len {
|
||||
bail!("arguments length doesn't match");
|
||||
}
|
||||
let new_env = Env::chain(&ie);
|
||||
for (name, value) in ps.iter().zip(evaled_iter) {
|
||||
new_env.borrow_mut().define(name.to_string(), value);
|
||||
}
|
||||
ctx.trace_call_start(*id);
|
||||
c = Cont::Eval { c: Rc::new(Cont::Ret { e: Rc::clone(&e), id: *id, c: nc }) };
|
||||
f = Rc::clone(&b);
|
||||
e = new_env;
|
||||
},
|
||||
Form::Prim(p) => {
|
||||
ctx.trace_prim(p);
|
||||
let a = evaled_iter.next().unwrap();
|
||||
f = match comb.prim().unwrap() {
|
||||
Prim::Car => a.car()?,
|
||||
Prim::Cdr => a.cdr()?,
|
||||
_ => {
|
||||
let b = evaled_iter.next().unwrap();
|
||||
match comb.prim().unwrap() {
|
||||
Prim::Add => Form::new_int(a.int()? + b.int()?),
|
||||
Prim::Sub => Form::new_int(a.int()? - b.int()?),
|
||||
Prim::Mul => Form::new_int(a.int()? * b.int()?),
|
||||
Prim::Div => Form::new_int(a.int()? / b.int()?),
|
||||
Prim::Mod => Form::new_int(a.int()? % b.int()?),
|
||||
Prim::Cons => Form::new_pair(a, b),
|
||||
Prim::Eq => Form::new_bool(a.my_eq(&b)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
};
|
||||
c = (*nc).clone();
|
||||
},
|
||||
_ => {
|
||||
bail!("tried to call a non-comb {}", comb)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
f = to_go.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Call { evaled, to_go: to_go.cdr()?, c: nc }) };
|
||||
}
|
||||
}
|
||||
Cont::Eval { c: nc } => {
|
||||
let tmp = f;
|
||||
match &*tmp {
|
||||
Form::Symbol(s, _id) => {
|
||||
ctx.trace_lookup(s);
|
||||
f = e.borrow().lookup(s)?;
|
||||
c = (*nc).clone();
|
||||
},
|
||||
Form::Pair(car, cdr, _id) => {
|
||||
match &**car {
|
||||
Form::Symbol(s, _id) if s == "if" => {
|
||||
f = cdr.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "if", to_go: cdr.cdr()?, c: nc }) };
|
||||
}
|
||||
// and/or has to short-circut, so special form
|
||||
// just like Scheme (bad ;) )
|
||||
Form::Symbol(s, _id) if s == "or" => {
|
||||
f = cdr.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "or", to_go: cdr.cdr()?, c: nc }) };
|
||||
}
|
||||
Form::Symbol(s, _id) if s == "and" => {
|
||||
f = cdr.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "and", to_go: cdr.cdr()?, c: nc }) };
|
||||
}
|
||||
Form::Symbol(s, _id) if s == "begin" => {
|
||||
f = cdr.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "begin", to_go: cdr.cdr()?, c: nc }) };
|
||||
}
|
||||
Form::Symbol(s, _id) if s == "debug" => {
|
||||
f = cdr.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "debug", to_go: cdr.cdr()?, c: nc }) };
|
||||
}
|
||||
// This is a fast and loose ~simple lisp~, so just go for it
|
||||
// and can have convention that this is always top levelish
|
||||
Form::Symbol(s, _id) if s == "define" => {
|
||||
// note the swap, evaluating the second not the first (define a value..)
|
||||
f = cdr.cdr()?.car()?;
|
||||
c = Cont::Eval { c: Rc::new(Cont::Prim { s: "define", to_go: cdr.car()?, c: nc }) };
|
||||
}
|
||||
Form::Symbol(s, _id) if s == "quote" => {
|
||||
f = cdr.car()?;
|
||||
ctx.trace_constant(&f);
|
||||
c = (*nc).clone();
|
||||
}
|
||||
// (lambda (a b) body)
|
||||
Form::Symbol(s, _id) if s == "lambda" => {
|
||||
let mut params_vec = vec![];
|
||||
let mut params = cdr.car()?;
|
||||
while let Ok((ncar, ncdr)) = params.pair() {
|
||||
params_vec.push(ncar.sym()?.to_string());
|
||||
params = ncdr;
|
||||
}
|
||||
let body = cdr.cdr()?.car()?;
|
||||
// Later on, the id of the closure should maybe be augmented
|
||||
// or replaced with the id of the code it was made out of?
|
||||
ctx.trace_lambda(¶ms_vec, &e, &body);
|
||||
f = Form::new_closure(params_vec, Rc::clone(&e), body, &mut ctx);
|
||||
c = (*nc).clone();
|
||||
}
|
||||
_ => {
|
||||
f = Rc::clone(car);
|
||||
c = Cont::Eval { c: Rc::new(Cont::Call { evaled: vec![], to_go: Rc::clone(cdr), c: nc }) };
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// value, no eval
|
||||
f = tmp;
|
||||
ctx.trace_constant(&f);
|
||||
c = (*nc).clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// optimized as a function based off side table of id keyed -> opt
|
||||
// that id might be nice for debugging too
|
||||
// Symbol ID's could actually be used for environment lookups
|
||||
// this is just interning
|
||||
// todo, strings not symbols?
|
||||
impl From<String> for Form { fn from(item: String) -> Self { Form::Symbol(item, RefCell::new(None)) } }
|
||||
impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned(), RefCell::new(None)) } }
|
||||
impl From<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
|
||||
impl From<bool> for Form { fn from(item: bool) -> Self { Form::Bool(item) } }
|
||||
impl<A: Into<Form>, B: Into<Form>> From<(A, B)> for Form {
|
||||
fn from(item: (A, B)) -> Self {
|
||||
Form::Pair(Rc::new(item.0.into()), Rc::new(item.1.into()), RefCell::new(None))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Form {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Form::Nil => write!(f, "nil"),
|
||||
Form::Int(i) => write!(f, "{i}"),
|
||||
Form::Bool(b) => write!(f, "{b}"),
|
||||
Form::Symbol(s, _id) => write!(f, "'{s}"),
|
||||
Form::Pair(car, cdr, _id) => {
|
||||
write!(f, "({}", car)?;
|
||||
let mut traverse: Rc<Form> = Rc::clone(cdr);
|
||||
loop {
|
||||
match &*traverse {
|
||||
Form::Pair(ref carp, ref cdrp, ref _id) => {
|
||||
write!(f, " {}", carp)?;
|
||||
traverse = Rc::clone(cdrp);
|
||||
},
|
||||
Form::Nil => {
|
||||
write!(f, ")")?;
|
||||
return Ok(());
|
||||
},
|
||||
x => {
|
||||
write!(f, ". {x})")?;
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Form::Closure(params, inner_env, code, id) => {
|
||||
write!(f, "<closure{} {:?}>", id, params)
|
||||
}
|
||||
Form::Prim(p) => {
|
||||
match p {
|
||||
Prim::Add => write!(f, "+"),
|
||||
Prim::Sub => write!(f, "-"),
|
||||
Prim::Mul => write!(f, "*"),
|
||||
Prim::Div => write!(f, "/"),
|
||||
Prim::Mod => write!(f, "%"),
|
||||
Prim::Cons => write!(f, "cons"),
|
||||
Prim::Car => write!(f, "car"),
|
||||
Prim::Cdr => write!(f, "cdr"),
|
||||
Prim::Eq => write!(f, "="),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
sl/src/main.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
#[macro_use] extern crate lalrpop_util;
|
||||
lalrpop_mod!(pub grammar);
|
||||
|
||||
use std::rc::Rc;
|
||||
use anyhow::Result;
|
||||
|
||||
use sl::eval;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let input = "
|
||||
(begin
|
||||
(debug 1)
|
||||
;(debug (= 1 2))
|
||||
;(debug (+ 2 3))
|
||||
;(define a (+ 1 (* 3 4)))
|
||||
|
||||
;(define fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1))))))
|
||||
;(debug 'gonna_fact_it)
|
||||
;(debug fact)
|
||||
;(debug (fact 400))
|
||||
|
||||
;(define fact2 (lambda (n a) (if (= n 1) a (fact2 (- n 1) (* n a)))))
|
||||
;(debug 'gonna_fact2_it)
|
||||
;(debug fact2)
|
||||
;(debug (fact2 400 1))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(define faft (lambda (n) (if (= n 1) (debug 1) (+ n (faft (- n 1))))))
|
||||
(debug 'gonna_faft_it)
|
||||
(debug faft)
|
||||
(debug (faft 6))
|
||||
;(debug (faft 400))
|
||||
|
||||
;(define faft2 (lambda (n a) (if (= n 1) a (faft2 (- n 1) (+ n a)))))
|
||||
;(debug 'gonna_faft2_it)
|
||||
;(debug faft2)
|
||||
;(debug (faft2 400 1))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;(define fib (lambda (n) (if (or (= n 0) (= n 1)) 1 (+ (fib (- n 1)) (fib (- n 2))))))
|
||||
;(debug 'gonna_fib_it)
|
||||
;(debug fib)
|
||||
;(debug (fib 10))
|
||||
|
||||
;(debug a)
|
||||
;(define b (cons 1 (cons 2 (cons 3 nil))))
|
||||
;(debug b)
|
||||
;(debug (car b))
|
||||
;(debug (cdr b))
|
||||
(if (= 1 2) (+ 2 3) (* 2 2))
|
||||
)
|
||||
";
|
||||
let parsed_input = Rc::new(grammar::TermParser::new().parse(input)?);
|
||||
//println!("Hello, world: {parsed_input:?}");
|
||||
println!("Hello, world: {parsed_input}");
|
||||
let evaled = eval(Rc::clone(&parsed_input))?;
|
||||
println!("evaled: {evaled}");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo
|
||||
echo "Partially Evaluating & compiling " $@
|
||||
echo "Source is"
|
||||
cat $@
|
||||
echo
|
||||
touch csc_out.wasm && rm csc_out.wasm && time scheme --script ../partial_eval.scm $@
|
||||
echo
|
||||
echo "Running"
|
||||
echo
|
||||
wasmtime ./csc_out.wasm
|
||||
echo
|
||||
echo
|
||||
@@ -1,156 +0,0 @@
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
if (vau de (con than & else) (cond (eval con de) (eval than de)
|
||||
(> (len else) 0) (eval (idx else 0) de)
|
||||
true false))
|
||||
|
||||
map (lambda (f5 l5)
|
||||
; now maybe errors on can't find helper?
|
||||
(let (helper (rec-lambda recurse (f4 l4 n4 i4)
|
||||
(cond (= i4 (len l4)) n4
|
||||
(<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array
|
||||
(f4 (idx l4 (+ i4 0)))
|
||||
(f4 (idx l4 (+ i4 1)))
|
||||
(f4 (idx l4 (+ i4 2)))
|
||||
(f4 (idx l4 (+ i4 3)))
|
||||
)) (+ i4 4))
|
||||
true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1)))))
|
||||
(helper f5 l5 (array) 0)))
|
||||
|
||||
|
||||
map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(cond (= i (len l)) n
|
||||
(<= i (- (len l) 4)) (recurse f l (concat n (array
|
||||
(f (+ i 0) (idx l (+ i 0)))
|
||||
(f (+ i 1) (idx l (+ i 1)))
|
||||
(f (+ i 2) (idx l (+ i 2)))
|
||||
(f (+ i 3) (idx l (+ i 3)))
|
||||
)) (+ i 4))
|
||||
true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
filter_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1))
|
||||
(recurse f l n (+ i 1))))))
|
||||
(helper f l (array) 0)))
|
||||
filter (lambda (f l) (filter_i (lambda (i x) (f x)) l))
|
||||
|
||||
foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z
|
||||
(recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1)))))
|
||||
(lambda (f z & vs) (helper f z vs 0)))
|
||||
|
||||
not (lambda (x) (if x false true))
|
||||
|
||||
; Huge thanks to Oleg Kiselyov for his fantastic website
|
||||
; http://okmij.org/ftp/Computation/fixed-point-combinators.html
|
||||
Y* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l))))
|
||||
vY* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l))))
|
||||
|
||||
let-rec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
let-vrec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
|
||||
flat_map (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
flat_map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f i (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
; with all this, we make a destrucutring-capable let
|
||||
let (let (
|
||||
destructure_helper (rec-lambda recurse (vs i r)
|
||||
(cond (= (len vs) i) r
|
||||
(array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i)))
|
||||
;new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (slice (idx vs i) 1 -1))
|
||||
new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i))
|
||||
)
|
||||
(recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1))))))
|
||||
true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2))))
|
||||
))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de)))
|
||||
|
||||
; and a destructuring-capable lambda!
|
||||
only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true
|
||||
(symbol? (idx a i)) (recurse a (+ i 1))
|
||||
true false))
|
||||
|
||||
; Note that if macro_helper is inlined, the mapping lambdas will close over
|
||||
; se, and then not be able to be taken in as values to the maps, and the vau
|
||||
; will fail to partially evaluate away.
|
||||
lambda (let (macro_helper (lambda (p b) (let (
|
||||
sym_params (map (lambda (param) (if (symbol? param) param
|
||||
(str-to-symbol (str param)))) p)
|
||||
body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b)
|
||||
) (array vau sym_params body))))
|
||||
(vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se)
|
||||
(wrap (eval (macro_helper p b) se)))))
|
||||
|
||||
; and rec-lambda - yes it's the same definition again
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
nil (array)
|
||||
or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1)))))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp)))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
|
||||
|
||||
monad (array 'write 1 "entering debug time!" (vau (written code) (array 'exit (debug))))
|
||||
|
||||
)
|
||||
monad
|
||||
)
|
||||
;(array 'write 1 "test_self_out2" (vau (written code) 7))
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
; this would be the macro style version (((
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
;)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de)) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1 +0,0 @@
|
||||
(+ 1 2)
|
||||
@@ -1 +0,0 @@
|
||||
(wrap (vau () (+ 1 2)))
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
((wrap (vau (quote)
|
||||
|
||||
|
||||
(vau () (array (quote a) (+ 1 2)))
|
||||
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1,154 +0,0 @@
|
||||
((wrap (vau root_env (quote)
|
||||
((wrap (vau (let1)
|
||||
(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se)))
|
||||
(let1 current-env (vau de () de)
|
||||
(let1 cons (lambda (h t) (concat (array h) t))
|
||||
(let1 Y (lambda (f3)
|
||||
((lambda (x1) (x1 x1))
|
||||
(lambda (x2) (f3 (lambda (& y) (lapply (x2 x2) y))))))
|
||||
(let1 vY (lambda (f)
|
||||
((lambda (x3) (x3 x3))
|
||||
(lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1))))))
|
||||
(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2)
|
||||
true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2)))))
|
||||
(let (
|
||||
lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args)))))
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
if (vau de (con than & else) (cond (eval con de) (eval than de)
|
||||
(> (len else) 0) (eval (idx else 0) de)
|
||||
true false))
|
||||
|
||||
map (lambda (f5 l5)
|
||||
; now maybe errors on can't find helper?
|
||||
(let (helper (rec-lambda recurse (f4 l4 n4 i4)
|
||||
(cond (= i4 (len l4)) n4
|
||||
(<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array
|
||||
(f4 (idx l4 (+ i4 0)))
|
||||
(f4 (idx l4 (+ i4 1)))
|
||||
(f4 (idx l4 (+ i4 2)))
|
||||
(f4 (idx l4 (+ i4 3)))
|
||||
)) (+ i4 4))
|
||||
true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1)))))
|
||||
(helper f5 l5 (array) 0)))
|
||||
|
||||
|
||||
map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(cond (= i (len l)) n
|
||||
(<= i (- (len l) 4)) (recurse f l (concat n (array
|
||||
(f (+ i 0) (idx l (+ i 0)))
|
||||
(f (+ i 1) (idx l (+ i 1)))
|
||||
(f (+ i 2) (idx l (+ i 2)))
|
||||
(f (+ i 3) (idx l (+ i 3)))
|
||||
)) (+ i 4))
|
||||
true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
filter_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1))
|
||||
(recurse f l n (+ i 1))))))
|
||||
(helper f l (array) 0)))
|
||||
filter (lambda (f l) (filter_i (lambda (i x) (f x)) l))
|
||||
|
||||
not (lambda (x) (if x false true))
|
||||
|
||||
; Huge thanks to Oleg Kiselyov for his fantastic website
|
||||
; http://okmij.org/ftp/Computation/fixed-point-combinators.html
|
||||
Y* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l))))
|
||||
vY* (lambda (& l)
|
||||
((lambda (u) (u u))
|
||||
(lambda (p)
|
||||
(map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l))))
|
||||
|
||||
let-rec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
let-vrec (vau de (name_func body)
|
||||
(let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func)
|
||||
funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func)
|
||||
overwrite_name (idx name_func (- (len name_func) 2)))
|
||||
(eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs)))
|
||||
(lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names)))
|
||||
body) de)))
|
||||
|
||||
flat_map (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
flat_map_i (lambda (f l)
|
||||
(let (helper (rec-lambda recurse (f l n i)
|
||||
(if (= i (len l))
|
||||
n
|
||||
(recurse f l (concat n (f i (idx l i))) (+ i 1)))))
|
||||
(helper f l (array) 0)))
|
||||
|
||||
; with all this, we make a destrucutring-capable let
|
||||
let (let (
|
||||
destructure_helper (rec-lambda recurse (vs i r)
|
||||
(cond (= (len vs) i) r
|
||||
(array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i)))
|
||||
;new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (slice (idx vs i) 1 -1))
|
||||
new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i))
|
||||
)
|
||||
(recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1))))))
|
||||
true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2))))
|
||||
))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de)))
|
||||
|
||||
; and a destructuring-capable lambda!
|
||||
only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true
|
||||
(symbol? (idx a i)) (recurse a (+ i 1))
|
||||
true false))
|
||||
|
||||
; Note that if macro_helper is inlined, the mapping lambdas will close over
|
||||
; se, and then not be able to be taken in as values to the maps, and the vau
|
||||
; will fail to partially evaluate away.
|
||||
lambda (let (macro_helper (lambda (p b) (let (
|
||||
sym_params (map (lambda (param) (if (symbol? param) param
|
||||
(str-to-symbol (str param)))) p)
|
||||
body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b)
|
||||
) (array vau sym_params body))))
|
||||
(vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se)
|
||||
(wrap (eval (macro_helper p b) se)))))
|
||||
|
||||
; and rec-lambda - yes it's the same definition again
|
||||
rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se))
|
||||
|
||||
nil (array)
|
||||
or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1)))))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true
|
||||
(= (+ 1 i) (len bs)) (idx bs i)
|
||||
true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp)))))
|
||||
(vau se (& bs) (eval (macro_helper bs 0) se)))
|
||||
|
||||
|
||||
test17 (or false 1 "a" true)
|
||||
test18 (and 1 "a" nil true)
|
||||
monad (array 'write 1 "test_self_out2" (vau (written code) (array 'exit (or written code) test17 (or false nil 0) (and written code) test18 (and nil 0 false))))
|
||||
|
||||
)
|
||||
monad
|
||||
)
|
||||
;(array 'write 1 "test_self_out2" (vau (written code) 7))
|
||||
; end of all lets
|
||||
))))))
|
||||
; impl of let1
|
||||
; this would be the macro style version (((
|
||||
)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de)))
|
||||
;)) (vau de (s v b) (eval (array (array vau (array s) b) (eval v de)) de)))
|
||||
; impl of quote
|
||||
)) (vau (x5) x5))
|
||||
@@ -1 +0,0 @@
|
||||
(vau () (+ 1 2))
|
||||
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 |