mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
Add SectorLambda
This commit is contained in:
parent
741c836e9d
commit
f5831a62fa
21 changed files with 3275 additions and 0 deletions
2
Makefile
2
Makefile
|
@ -157,6 +157,8 @@ include examples/examples.mk
|
||||||
include examples/pyapp/pyapp.mk
|
include examples/pyapp/pyapp.mk
|
||||||
include tool/decode/lib/decodelib.mk
|
include tool/decode/lib/decodelib.mk
|
||||||
include tool/decode/decode.mk
|
include tool/decode/decode.mk
|
||||||
|
include tool/lambda/lib/lib.mk
|
||||||
|
include tool/lambda/lambda.mk
|
||||||
include tool/hash/hash.mk
|
include tool/hash/hash.mk
|
||||||
include tool/net/net.mk
|
include tool/net/net.mk
|
||||||
include tool/viz/viz.mk
|
include tool/viz/viz.mk
|
||||||
|
|
77
tool/lambda/asc2bin.c
Normal file
77
tool/lambda/asc2bin.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Copying of this file is authorized only if (1) you are Justine Tunney, or │
|
||||||
|
│ (2) you make absolutely no changes to your copy. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES │
|
||||||
|
│ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF │
|
||||||
|
│ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR │
|
||||||
|
│ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │
|
||||||
|
│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN │
|
||||||
|
│ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF │
|
||||||
|
│ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
#define USAGE \
|
||||||
|
" [-?h] [FILE...] <binary.txt >binary.bin\n\
|
||||||
|
Converts ASCII binary to ACTUAL binary, e.g.\n\
|
||||||
|
\n\
|
||||||
|
$ { printf 'λx.x' | o/lam2bin | o/asc2bin; printf abc; } | o/Blc\n\
|
||||||
|
abc\n\
|
||||||
|
\n\
|
||||||
|
$ printf '\n\
|
||||||
|
(00 (01 (01 10 ((01 (00 (01 10 10))\n\
|
||||||
|
(00000000 (01 (01 110 ((01 11110 11110)))\n\
|
||||||
|
(00 (01 (01 10 11110) 110)))))))\n\
|
||||||
|
(0000 10)))\n\
|
||||||
|
' | asc2bin | xxd -b\n\
|
||||||
|
00000000: 00010110 01000110 10000000 00010111 00111110 11110000 .F..>.\n\
|
||||||
|
00000006: 10110111 10110000 01000000 ..@\n\
|
||||||
|
\n\
|
||||||
|
FLAGS\n\
|
||||||
|
\n\
|
||||||
|
-h Help\n\
|
||||||
|
-? Help\n"
|
||||||
|
|
||||||
|
void LoadFlags(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
const char *prog;
|
||||||
|
prog = argc ? argv[0] : "asc2bin";
|
||||||
|
while ((i = getopt(argc, argv, "?h")) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
fputs("Usage: ", stdout);
|
||||||
|
fputs(prog, stdout);
|
||||||
|
fputs(USAGE, stdout);
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
fputs("Usage: ", stderr);
|
||||||
|
fputs(prog, stderr);
|
||||||
|
fputs(USAGE, stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int i, b, c, n;
|
||||||
|
LoadFlags(argc, argv);
|
||||||
|
n = c = i = 0;
|
||||||
|
while ((b = GetBit(stdin)) != -1) {
|
||||||
|
c |= b << (7 - n);
|
||||||
|
if (++n == 8) {
|
||||||
|
fputc(c, stdout);
|
||||||
|
c = 0;
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n) {
|
||||||
|
fputc(c, stdout);
|
||||||
|
}
|
||||||
|
}
|
156
tool/lambda/blcdump.c
Normal file
156
tool/lambda/blcdump.c
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Copying of this file is authorized only if (1) you are Justine Tunney, or │
|
||||||
|
│ (2) you make absolutely no changes to your copy. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES │
|
||||||
|
│ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF │
|
||||||
|
│ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR │
|
||||||
|
│ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │
|
||||||
|
│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN │
|
||||||
|
│ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF │
|
||||||
|
│ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/rlimit.h"
|
||||||
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
|
#include "libc/unicode/locale.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Binary Lambda Calculus Dump Utility, e.g.
|
||||||
|
*
|
||||||
|
* $ echo 0000001110 | o//blcdump -b 2>/dev/null
|
||||||
|
* (λ (λ (λ 2)))
|
||||||
|
*
|
||||||
|
* The term rom is printed to stderr along with all skewed overlapping
|
||||||
|
* perspectives on the in-memory representation.
|
||||||
|
*
|
||||||
|
* $ echo 0000001110 | o//blcdump -b >/dev/null
|
||||||
|
* .long ABS # 0=3: (λ (λ (λ 2)))
|
||||||
|
* .long ABS # 1=3: (λ (λ 2))
|
||||||
|
* .long ABS # 2=3: (λ 2)
|
||||||
|
* .long VAR # 3=1: 2
|
||||||
|
* .long 2 # 4=2: (⋯ ⋯)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USAGE \
|
||||||
|
" [-?hbBnNlS] [FILE...] <stdin >expr.txt 2>memory.txt\n\
|
||||||
|
Binary Lambda Calculus Dump Tool\n\
|
||||||
|
\n\
|
||||||
|
FLAGS\n\
|
||||||
|
\n\
|
||||||
|
-h Help\n\
|
||||||
|
-b 8-bit binary mode\n\
|
||||||
|
-B debug print binary\n\
|
||||||
|
-l print lambda notation\n\
|
||||||
|
-n disables name rewriting rules\n\
|
||||||
|
-N disables most unicode symbolism\n"
|
||||||
|
|
||||||
|
void PrintUsage(const char *prog, int rc, FILE *f) {
|
||||||
|
fputs("Usage: ", f);
|
||||||
|
fputs(prog, f);
|
||||||
|
fputs(USAGE, f);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadFlags(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
const char *prog;
|
||||||
|
prog = argc ? argv[0] : "blcdump";
|
||||||
|
while ((i = getopt(argc, argv, "?hubBnNlS")) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case 'b':
|
||||||
|
binary = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
noname = 1;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
asciiname = 1;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
style = 1;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
style = 2;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
safer = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
PrintUsage(prog, 0, stdout);
|
||||||
|
default:
|
||||||
|
PrintUsage(prog, 1, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expand(int c) {
|
||||||
|
if (end >= TERMS) Error(5, "OUT OF TERMS");
|
||||||
|
mem[end++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpandBit(int b) {
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(VAR);
|
||||||
|
Expand(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpandList(int next) {
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(APP);
|
||||||
|
Expand(next);
|
||||||
|
Expand(APP);
|
||||||
|
Expand(2);
|
||||||
|
Expand(VAR);
|
||||||
|
Expand(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpandItem(int b) {
|
||||||
|
ExpandList(8);
|
||||||
|
ExpandBit(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpandByte(int b) {
|
||||||
|
ExpandList(4 + 8 * (7 + 4));
|
||||||
|
ExpandItem((b >> 0) & 1);
|
||||||
|
ExpandItem((b >> 1) & 1);
|
||||||
|
ExpandItem((b >> 2) & 1);
|
||||||
|
ExpandItem((b >> 3) & 1);
|
||||||
|
ExpandItem((b >> 4) & 1);
|
||||||
|
ExpandItem((b >> 5) & 1);
|
||||||
|
ExpandItem((b >> 6) & 1);
|
||||||
|
ExpandItem((b >> 7) & 1);
|
||||||
|
ExpandBit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct Parse p;
|
||||||
|
struct rlimit rlim = {512 * 1024 * 1024, 512 * 1024 * 1024};
|
||||||
|
setrlimit(RLIMIT_AS, &rlim);
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
setvbuf(stdout, 0, _IOFBF, 0);
|
||||||
|
setvbuf(stderr, 0, _IOLBF, 0);
|
||||||
|
LoadFlags(argc, argv);
|
||||||
|
#if DEBUG
|
||||||
|
logh = fopen("o//log", "w");
|
||||||
|
fprintf(logh, " IP END HEAP %-*s NOM MESSAGE\n", LOC, "LOC");
|
||||||
|
setvbuf(logh, 0, _IOLBF, 0);
|
||||||
|
#endif
|
||||||
|
end = 32;
|
||||||
|
for (; !feof(stdin); ip = end) {
|
||||||
|
p = Parse(1, stdin);
|
||||||
|
if (p.n) {
|
||||||
|
Print(p.i, 1, 0, stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
Dump(p.i, p.i + p.n, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
324
tool/lambda/bru2bin.c
Normal file
324
tool/lambda/bru2bin.c
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/unicode/locale.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
|
||||||
|
#define USAGE \
|
||||||
|
" [-?h01] <lambda.txt >binary.txt\n\
|
||||||
|
Converts de Bruijn notation to ASCII binary, e.g.\n\
|
||||||
|
\n\
|
||||||
|
$ printf 'λ (λ 1 (0 0)) (λ 1 (0 0)))' | lam2bin\n\
|
||||||
|
000100011100110100001110011010\n\
|
||||||
|
\n\
|
||||||
|
FLAGS\n\
|
||||||
|
\n\
|
||||||
|
-h Help\n\
|
||||||
|
-? Help\n\
|
||||||
|
-0 0-based indexing\n\
|
||||||
|
-1 1-based indexing\n"
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
int t, x;
|
||||||
|
struct Node *l, *r;
|
||||||
|
};
|
||||||
|
|
||||||
|
int sp;
|
||||||
|
int end;
|
||||||
|
int unget;
|
||||||
|
int indexing;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
static void LoadFlags(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
const char *prog;
|
||||||
|
prog = argc ? argv[0] : "lam2bin";
|
||||||
|
while ((i = getopt(argc, argv, "?h01")) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case '0':
|
||||||
|
indexing = 0;
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
indexing = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
fputs("Usage: ", stdout);
|
||||||
|
fputs(prog, stdout);
|
||||||
|
fputs(USAGE, stdout);
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
fputs("Usage: ", stderr);
|
||||||
|
fputs(prog, stderr);
|
||||||
|
fputs(USAGE, stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wontreturn static void Error(int rc, const char *s, ...) {
|
||||||
|
va_list va;
|
||||||
|
fflush(stdout);
|
||||||
|
fputs("\33[1;31merror\33[37m: ", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
va_start(va, s);
|
||||||
|
kvprintf(s, va);
|
||||||
|
va_end(va);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *NewNode(int t, int x, struct Node *l, struct Node *r) {
|
||||||
|
struct Node *n;
|
||||||
|
n = malloc(sizeof(struct Node));
|
||||||
|
n->t = t;
|
||||||
|
n->x = x;
|
||||||
|
n->l = l;
|
||||||
|
n->r = r;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Greed(void) {
|
||||||
|
int c, t;
|
||||||
|
for (t = 0;;) {
|
||||||
|
if (unget) {
|
||||||
|
c = unget;
|
||||||
|
unget = 0;
|
||||||
|
} else if (str) {
|
||||||
|
if (*str) {
|
||||||
|
c = *str++;
|
||||||
|
} else {
|
||||||
|
str = 0;
|
||||||
|
c = fgetwc(stdin);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c = fgetwc(stdin);
|
||||||
|
}
|
||||||
|
if (c == EOF) return c;
|
||||||
|
if (!t) {
|
||||||
|
if (c == '#' || c == ';') {
|
||||||
|
t = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (c == '\n') {
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!str) {
|
||||||
|
switch (c) {
|
||||||
|
case L'⊥':
|
||||||
|
str = "(\\ab.b)";
|
||||||
|
continue;
|
||||||
|
case L'⊤':
|
||||||
|
str = "(\\ab.a)";
|
||||||
|
continue;
|
||||||
|
#if 0
|
||||||
|
case L'0':
|
||||||
|
str = "(\\ab.b)";
|
||||||
|
continue;
|
||||||
|
case L'1':
|
||||||
|
str = "(\\ab.ab)";
|
||||||
|
continue;
|
||||||
|
case L'2':
|
||||||
|
str = "(\\ab.a(ab))";
|
||||||
|
continue;
|
||||||
|
case L'3':
|
||||||
|
str = "(\\ab.a(a(ab)))";
|
||||||
|
continue;
|
||||||
|
case L'4':
|
||||||
|
str = "(\\ab.a(a(a(ab))))";
|
||||||
|
continue;
|
||||||
|
case L'5':
|
||||||
|
str = "(\\ab.a(a(a(a(ab)))))";
|
||||||
|
continue;
|
||||||
|
case L'6':
|
||||||
|
str = "(\\ab.a(a(a(a(a(ab))))))";
|
||||||
|
continue;
|
||||||
|
case L'7':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(ab)))))))";
|
||||||
|
continue;
|
||||||
|
case L'8':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(a(ab))))))))";
|
||||||
|
continue;
|
||||||
|
case L'9':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(a(a(ab)))))))))";
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
case L'ω':
|
||||||
|
str = "(\\x.xx)";
|
||||||
|
continue;
|
||||||
|
case L'Ω':
|
||||||
|
str = "((\\x.xx)(\\x.xx))";
|
||||||
|
continue;
|
||||||
|
case L'Y':
|
||||||
|
str = "(\\f.(\\x.f(xx))(\\x.f(xx)))";
|
||||||
|
continue;
|
||||||
|
case L'∧':
|
||||||
|
str = "(\\ab.aba)";
|
||||||
|
continue;
|
||||||
|
case L'∨':
|
||||||
|
str = "(\\ab.aab)";
|
||||||
|
continue;
|
||||||
|
case L'⊻':
|
||||||
|
str = "(\\ab.a((\\c.c(\\de.e)(\\de.d))b)b)";
|
||||||
|
continue;
|
||||||
|
case L'¬':
|
||||||
|
str = "(\\a.a(\\bc.c)(\\bc.b))";
|
||||||
|
continue;
|
||||||
|
case L'+':
|
||||||
|
str = "(\\abcd.ac(bcd))";
|
||||||
|
continue;
|
||||||
|
case L'*':
|
||||||
|
str = "(\\abc.a(bc))";
|
||||||
|
continue;
|
||||||
|
case L'^':
|
||||||
|
str = "(\\ab.ba)";
|
||||||
|
continue;
|
||||||
|
case L'-':
|
||||||
|
str = "(\\ab.b(\\cde.c(\\fg.g(fd))(\\f.e)(\\f.f))a)";
|
||||||
|
continue;
|
||||||
|
case L'/':
|
||||||
|
str = "(\\a.(\\b.(\\c.cc)(\\c.b(cc)))(\\bcdef.(\\g.(\\h.h(\\ijk.k)("
|
||||||
|
"\\ij.i))g((\\hi.i)ef)(e(bgdef)))((\\gh.h(\\ijk.i(\\lm.m(lj))("
|
||||||
|
"\\l.k)(\\l.l))g)cd))((\\bcd.c(bcd))a))";
|
||||||
|
continue;
|
||||||
|
case L'Я':
|
||||||
|
str = "(\\a.a((\\b.bb)(\\bcde.d(bb)(\\f.fce)))(\\bc.c))";
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Need(void) {
|
||||||
|
int c;
|
||||||
|
if ((c = Greed()) != EOF) return c;
|
||||||
|
Error(1, "unfinished expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *Parse1(void) {
|
||||||
|
wint_t c;
|
||||||
|
int i, oldsp;
|
||||||
|
struct Node *r, *p, *q, *s;
|
||||||
|
do {
|
||||||
|
if ((c = Greed()) == EOF) return 0;
|
||||||
|
} while (iswspace(c));
|
||||||
|
if (c == L'λ' || c == '\\') {
|
||||||
|
oldsp = sp;
|
||||||
|
p = r = NewNode(0, 0, 0, 0);
|
||||||
|
++sp;
|
||||||
|
for (;;) {
|
||||||
|
c = Need();
|
||||||
|
if (c == L'λ' || c == '\\') {
|
||||||
|
p = p->l = NewNode(0, 0, 0, 0);
|
||||||
|
++sp;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
unget = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q = Parse1();
|
||||||
|
if (!q) Error(4, "lambda needs body");
|
||||||
|
p->l = q;
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
p->l = NewNode(2, 0, p->l, q);
|
||||||
|
}
|
||||||
|
sp = oldsp;
|
||||||
|
return r;
|
||||||
|
} else if (c == L'!') {
|
||||||
|
// intentionally trigger undefined variable
|
||||||
|
return NewNode(1, sp, 0, 0);
|
||||||
|
} else if (iswdigit(c)) {
|
||||||
|
i = 0;
|
||||||
|
for (;;) {
|
||||||
|
i *= 10;
|
||||||
|
i += c - '0';
|
||||||
|
c = Greed();
|
||||||
|
if (c == EOF) break;
|
||||||
|
if (!iswdigit(c)) {
|
||||||
|
unget = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i -= indexing;
|
||||||
|
if (i < 0) Error(5, "undefined variable: %lc", c);
|
||||||
|
return NewNode(1, i, 0, 0);
|
||||||
|
} else if (c == '(') {
|
||||||
|
p = r = Parse1();
|
||||||
|
if (!p) Error(6, "empty parenthesis");
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
r = NewNode(2, 0, r, q);
|
||||||
|
}
|
||||||
|
c = Need();
|
||||||
|
if (c != ')') Error(7, "expected closing parenthesis");
|
||||||
|
return r;
|
||||||
|
} else if (c == ')') {
|
||||||
|
unget = c;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
Error(8, "unexpected character: 0x%04x %lc", c, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *Parse(void) {
|
||||||
|
wint_t c;
|
||||||
|
int i, oldsp;
|
||||||
|
struct Node *r, *p, *q, *s;
|
||||||
|
p = r = Parse1();
|
||||||
|
if (!p) Error(6, "empty expression");
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
r = NewNode(2, 0, r, q);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Print(struct Node *p) {
|
||||||
|
int i;
|
||||||
|
if (p->t == 0) {
|
||||||
|
fputc('0', stdout);
|
||||||
|
fputc('0', stdout);
|
||||||
|
Print(p->l);
|
||||||
|
} else if (p->t == 1) {
|
||||||
|
for (i = -1; i < p->x; ++i) {
|
||||||
|
fputc('1', stdout);
|
||||||
|
}
|
||||||
|
fputc('0', stdout);
|
||||||
|
} else if (p->t == 2) {
|
||||||
|
fputc('0', stdout);
|
||||||
|
fputc('1', stdout);
|
||||||
|
Print(p->l);
|
||||||
|
Print(p->r);
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
LoadFlags(argc, argv);
|
||||||
|
Print(Parse());
|
||||||
|
}
|
305
tool/lambda/lam2bin.c
Normal file
305
tool/lambda/lam2bin.c
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/unicode/locale.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
|
||||||
|
#define USAGE \
|
||||||
|
" [-?h] <lambda.txt >binary.txt\n\
|
||||||
|
Converts lambda notation to ASCII binary, e.g.\n\
|
||||||
|
\n\
|
||||||
|
$ printf 'λf.(λx.f(xx))(λx.f(xx))' | lam2bin\n\
|
||||||
|
000100011100110100001110011010\n\
|
||||||
|
\n\
|
||||||
|
FLAGS\n\
|
||||||
|
\n\
|
||||||
|
-h Help\n\
|
||||||
|
-? Help\n"
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
int t, x;
|
||||||
|
struct Node *l, *r;
|
||||||
|
};
|
||||||
|
|
||||||
|
int sp;
|
||||||
|
int end;
|
||||||
|
int unget;
|
||||||
|
int args[1024];
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
static void LoadFlags(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
const char *prog;
|
||||||
|
prog = argc ? argv[0] : "lam2bin";
|
||||||
|
while ((i = getopt(argc, argv, "?h")) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
fputs("Usage: ", stdout);
|
||||||
|
fputs(prog, stdout);
|
||||||
|
fputs(USAGE, stdout);
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
fputs("Usage: ", stderr);
|
||||||
|
fputs(prog, stderr);
|
||||||
|
fputs(USAGE, stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wontreturn static void Error(int rc, const char *s, ...) {
|
||||||
|
va_list va;
|
||||||
|
fflush(stdout);
|
||||||
|
fputs("\33[1;31merror\33[37m: ", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
va_start(va, s);
|
||||||
|
kvprintf(s, va);
|
||||||
|
va_end(va);
|
||||||
|
fputc('\n', stderr);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *NewNode(int t, int x, struct Node *l, struct Node *r) {
|
||||||
|
struct Node *n;
|
||||||
|
n = malloc(sizeof(struct Node));
|
||||||
|
n->t = t;
|
||||||
|
n->x = x;
|
||||||
|
n->l = l;
|
||||||
|
n->r = r;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Greed(void) {
|
||||||
|
int c, t;
|
||||||
|
for (t = 0;;) {
|
||||||
|
if (unget) {
|
||||||
|
c = unget;
|
||||||
|
unget = 0;
|
||||||
|
} else if (str) {
|
||||||
|
if (*str) {
|
||||||
|
c = *str++;
|
||||||
|
} else {
|
||||||
|
str = 0;
|
||||||
|
c = fgetwc(stdin);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c = fgetwc(stdin);
|
||||||
|
}
|
||||||
|
if (c == EOF) return c;
|
||||||
|
if (!t) {
|
||||||
|
if (c == '#' || c == ';') {
|
||||||
|
t = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (c == '\n') {
|
||||||
|
t = 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (iswspace(c)) continue;
|
||||||
|
if (!str) {
|
||||||
|
switch (c) {
|
||||||
|
case L'⊥':
|
||||||
|
str = "(\\ab.b)";
|
||||||
|
continue;
|
||||||
|
case L'⊤':
|
||||||
|
str = "(\\ab.a)";
|
||||||
|
continue;
|
||||||
|
#if 0
|
||||||
|
case L'0':
|
||||||
|
str = "(\\ab.b)";
|
||||||
|
continue;
|
||||||
|
case L'1':
|
||||||
|
str = "(\\ab.ab)";
|
||||||
|
continue;
|
||||||
|
case L'2':
|
||||||
|
str = "(\\ab.a(ab))";
|
||||||
|
continue;
|
||||||
|
case L'3':
|
||||||
|
str = "(\\ab.a(a(ab)))";
|
||||||
|
continue;
|
||||||
|
case L'4':
|
||||||
|
str = "(\\ab.a(a(a(ab))))";
|
||||||
|
continue;
|
||||||
|
case L'5':
|
||||||
|
str = "(\\ab.a(a(a(a(ab)))))";
|
||||||
|
continue;
|
||||||
|
case L'6':
|
||||||
|
str = "(\\ab.a(a(a(a(a(ab))))))";
|
||||||
|
continue;
|
||||||
|
case L'7':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(ab)))))))";
|
||||||
|
continue;
|
||||||
|
case L'8':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(a(ab))))))))";
|
||||||
|
continue;
|
||||||
|
case L'9':
|
||||||
|
str = "(\\ab.a(a(a(a(a(a(a(a(ab)))))))))";
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
case L'ω':
|
||||||
|
str = "(\\x.xx)";
|
||||||
|
continue;
|
||||||
|
case L'Ω':
|
||||||
|
str = "((\\x.xx)(\\x.xx))";
|
||||||
|
continue;
|
||||||
|
case L'Y':
|
||||||
|
str = "(\\f.(\\x.f(xx))(\\x.f(xx)))";
|
||||||
|
continue;
|
||||||
|
case L'∧':
|
||||||
|
str = "(\\ab.aba)";
|
||||||
|
continue;
|
||||||
|
case L'∨':
|
||||||
|
str = "(\\ab.aab)";
|
||||||
|
continue;
|
||||||
|
case L'⊻':
|
||||||
|
str = "(\\ab.a((\\c.c(\\de.e)(\\de.d))b)b)";
|
||||||
|
continue;
|
||||||
|
case L'¬':
|
||||||
|
str = "(\\a.a(\\bc.c)(\\bc.b))";
|
||||||
|
continue;
|
||||||
|
case L'+':
|
||||||
|
str = "(\\abcd.ac(bcd))";
|
||||||
|
continue;
|
||||||
|
case L'*':
|
||||||
|
str = "(\\abc.a(bc))";
|
||||||
|
continue;
|
||||||
|
case L'^':
|
||||||
|
str = "(\\ab.ba)";
|
||||||
|
continue;
|
||||||
|
case L'-':
|
||||||
|
str = "(\\ab.b(\\cde.c(\\fg.g(fd))(\\f.e)(\\f.f))a)";
|
||||||
|
continue;
|
||||||
|
case L'/':
|
||||||
|
str = "(\\a.(\\b.(\\c.cc)(\\c.b(cc)))(\\bcdef.(\\g.(\\h.h(\\ijk.k)("
|
||||||
|
"\\ij.i))g((\\hi.i)ef)(e(bgdef)))((\\gh.h(\\ijk.i(\\lm.m(lj))("
|
||||||
|
"\\l.k)(\\l.l))g)cd))((\\bcd.c(bcd))a))";
|
||||||
|
continue;
|
||||||
|
case L'Я':
|
||||||
|
str = "(\\a.a((\\b.bb)(\\bcde.d(bb)(\\f.fce)))(\\bc.c))";
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Need(void) {
|
||||||
|
int c;
|
||||||
|
if ((c = Greed()) != EOF) return c;
|
||||||
|
Error(1, "unfinished expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *Parse1(void) {
|
||||||
|
wint_t c;
|
||||||
|
int i, oldsp;
|
||||||
|
struct Node *r, *p, *q, *s;
|
||||||
|
if ((c = Greed()) == EOF) return 0;
|
||||||
|
if (c == L'λ' || c == '\\') {
|
||||||
|
oldsp = sp;
|
||||||
|
c = Need();
|
||||||
|
if (!(isalnum(c) || c == '_')) Error(2, "lambda needs argument");
|
||||||
|
p = r = NewNode(0, 0, 0, 0);
|
||||||
|
args[sp++] = c;
|
||||||
|
while ((c = Need()) != '.') {
|
||||||
|
if (!(isalnum(c) || c == '_')) Error(3, "lambda needs argument");
|
||||||
|
p = p->l = NewNode(0, 0, 0, 0);
|
||||||
|
args[sp++] = c;
|
||||||
|
}
|
||||||
|
q = Parse1();
|
||||||
|
if (!q) Error(4, "lambda needs body");
|
||||||
|
p->l = q;
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
p->l = NewNode(2, 0, p->l, q);
|
||||||
|
}
|
||||||
|
sp = oldsp;
|
||||||
|
return r;
|
||||||
|
} else if (c == L'!') {
|
||||||
|
// intentionally trigger undefined variable
|
||||||
|
return NewNode(1, sp, 0, 0);
|
||||||
|
} else if (isalnum(c) || c == '_') {
|
||||||
|
for (i = sp; i--;) {
|
||||||
|
if (args[i] == c) {
|
||||||
|
i = sp - 1 - i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < 0) Error(5, "undefined variable: %d %lc", c, c);
|
||||||
|
return NewNode(1, i, 0, 0);
|
||||||
|
} else if (c == '(') {
|
||||||
|
p = r = Parse1();
|
||||||
|
if (!p) Error(6, "empty parenthesis");
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
r = NewNode(2, 0, r, q);
|
||||||
|
}
|
||||||
|
c = Need();
|
||||||
|
if (c != ')') Error(7, "expected closing parenthesis");
|
||||||
|
return r;
|
||||||
|
} else if (c == ')') {
|
||||||
|
unget = c;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
Error(8, "unexpected character: 0x%04x %lc", c, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Node *Parse(void) {
|
||||||
|
wint_t c;
|
||||||
|
int i, oldsp;
|
||||||
|
struct Node *r, *p, *q, *s;
|
||||||
|
p = r = Parse1();
|
||||||
|
if (!p) Error(6, "empty expression");
|
||||||
|
while ((q = Parse1())) {
|
||||||
|
r = NewNode(2, 0, r, q);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Print(struct Node *p) {
|
||||||
|
int i;
|
||||||
|
if (p->t == 0) {
|
||||||
|
fputc('0', stdout);
|
||||||
|
fputc('0', stdout);
|
||||||
|
Print(p->l);
|
||||||
|
} else if (p->t == 1) {
|
||||||
|
for (i = -1; i < p->x; ++i) {
|
||||||
|
fputc('1', stdout);
|
||||||
|
}
|
||||||
|
fputc('0', stdout);
|
||||||
|
} else if (p->t == 2) {
|
||||||
|
fputc('0', stdout);
|
||||||
|
fputc('1', stdout);
|
||||||
|
Print(p->l);
|
||||||
|
Print(p->r);
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
LoadFlags(argc, argv);
|
||||||
|
Print(Parse());
|
||||||
|
}
|
352
tool/lambda/lambda.c
Normal file
352
tool/lambda/lambda.c
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Copying of this file is authorized only if (1) you are Justine Tunney, or │
|
||||||
|
│ (2) you make absolutely no changes to your copy. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES │
|
||||||
|
│ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF │
|
||||||
|
│ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR │
|
||||||
|
│ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES │
|
||||||
|
│ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN │
|
||||||
|
│ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF │
|
||||||
|
│ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/rlimit.h"
|
||||||
|
#include "libc/calls/struct/sigaction.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/unicode/locale.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
#define USAGE \
|
||||||
|
" [-?hubBdsarvnNlS] <stdin >expr.txt\n\
|
||||||
|
Binary Lambda Calculus Virtual Machine\n\
|
||||||
|
\n\
|
||||||
|
FLAGS\n\
|
||||||
|
\n\
|
||||||
|
-h help\n\
|
||||||
|
-r rex log\n\
|
||||||
|
-b binary 8-bit i/o\n\
|
||||||
|
-B debug print binary\n\
|
||||||
|
-l print lambda notation\n\
|
||||||
|
-a action log [implies -r]\n\
|
||||||
|
-v variable log [implies -r]\n\
|
||||||
|
-s full machine state logging\n\
|
||||||
|
-n disables name rewriting rules\n\
|
||||||
|
-N disables most unicode symbolism\n\
|
||||||
|
-d dump terms on successful exit\n"
|
||||||
|
|
||||||
|
#define NIL 23
|
||||||
|
#define TRUE 27
|
||||||
|
#define FALSE 23
|
||||||
|
|
||||||
|
#define REF(c) (++(c)->refs, c)
|
||||||
|
|
||||||
|
static const char kRom[] = {
|
||||||
|
APP, 0, // 0 (λ 0 λ 0 (λ 0 wr0 wr1) put) (main gro)
|
||||||
|
ABS, // 2 λ 0 λ 0 (λ 0 wr0 wr1) put
|
||||||
|
APP, 0, // 3
|
||||||
|
VAR, 0, // 5
|
||||||
|
ABS, // 7
|
||||||
|
APP, // 8
|
||||||
|
ABS, // 9 λ 0 λ 0 wr0 wr1
|
||||||
|
APP, 2, // 10
|
||||||
|
VAR, // 12
|
||||||
|
IOP, // 13
|
||||||
|
ABS, // 14 λ 0 wr0 wr1
|
||||||
|
APP, 4, // 15
|
||||||
|
APP, 1, // 17
|
||||||
|
VAR, // 19
|
||||||
|
IOP, // 20 wr0
|
||||||
|
IOP, 0, // 21 wr1
|
||||||
|
ABS, // 23 (λλ 0) a.k.a. nil
|
||||||
|
ABS, // 24 exit
|
||||||
|
VAR, // 25
|
||||||
|
0, // 26 exit[0]
|
||||||
|
ABS, // 27 (λλ 1) a.k.a. true
|
||||||
|
ABS, // 28
|
||||||
|
VAR, 1, // 29
|
||||||
|
};
|
||||||
|
|
||||||
|
static int postdump;
|
||||||
|
static int kLazy[256];
|
||||||
|
|
||||||
|
void Quit(int sig) {
|
||||||
|
Dump(0, end, stderr);
|
||||||
|
exit(128 + sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintUsage(const char *prog, int rc, FILE *f) {
|
||||||
|
fputs("Usage: ", f);
|
||||||
|
fputs(prog, f);
|
||||||
|
fputs(USAGE, f);
|
||||||
|
exit(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Backref(int x) {
|
||||||
|
return x - (end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Expand(int c) {
|
||||||
|
if (end >= TERMS) Error(5, "OUT OF TERMS");
|
||||||
|
mem[end++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gc(struct Closure *p) {
|
||||||
|
struct Closure *t;
|
||||||
|
while (p && p != &root) {
|
||||||
|
if (--p->refs) break;
|
||||||
|
Gc(p->next);
|
||||||
|
t = p->envp;
|
||||||
|
p->envp = 0;
|
||||||
|
p->next = frep;
|
||||||
|
frep = p;
|
||||||
|
p = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Var(void) {
|
||||||
|
int i, x;
|
||||||
|
struct Closure *t, *e;
|
||||||
|
e = t = envp;
|
||||||
|
x = mem[ip + 1];
|
||||||
|
for (i = 0; i < x && e != &root; ++i) e = e->next;
|
||||||
|
if (e == &root) Error(10 + x, "UNDEFINED VARIABLE %d", x);
|
||||||
|
ip = e->term;
|
||||||
|
envp = REF(e->envp);
|
||||||
|
Gc(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gro(void) {
|
||||||
|
int c = fgetc(stdin);
|
||||||
|
if (c != -1) {
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(APP);
|
||||||
|
Expand(4);
|
||||||
|
Expand(APP);
|
||||||
|
Expand(Backref(binary ? kLazy[c] : c & 1 ? FALSE : TRUE));
|
||||||
|
Expand(VAR);
|
||||||
|
Expand(0);
|
||||||
|
} else {
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(VAR);
|
||||||
|
Expand(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Put(void) {
|
||||||
|
int bit;
|
||||||
|
long newip;
|
||||||
|
if (!binary) {
|
||||||
|
co = '0' + (ip & 1);
|
||||||
|
fputc(co, stdout);
|
||||||
|
newip = 2;
|
||||||
|
} else if (mem[ip + 1] & 1) { // ip ∈ {6,13}
|
||||||
|
fputc(co, stdout);
|
||||||
|
newip = 2;
|
||||||
|
} else { // ip ∈ {20,21}
|
||||||
|
newip = 9; // (λ 0 (λ 0 wr1 wr0))
|
||||||
|
bit = ip & 1;
|
||||||
|
co = (co * 2) | bit;
|
||||||
|
}
|
||||||
|
if (ferror(stdout)) {
|
||||||
|
exit(55);
|
||||||
|
}
|
||||||
|
ip = newip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bye(void) {
|
||||||
|
int rc = mem[ip + 2]; // (λ 0) [exitcode]
|
||||||
|
if (rc) Error(rc, "CONTINUATIONS EXHAUSTED");
|
||||||
|
if (postdump && !rc) Dump(0, end, stderr);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pops continuation and pushes it to environment
|
||||||
|
void Abs(void) {
|
||||||
|
if (!contp) Bye();
|
||||||
|
struct Closure *t = contp;
|
||||||
|
contp = t->next;
|
||||||
|
t->next = envp;
|
||||||
|
envp = t;
|
||||||
|
++ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Closure *Alloc(void) {
|
||||||
|
struct Closure *t;
|
||||||
|
if (!(t = frep)) {
|
||||||
|
if (!(t = Calloc(1, sizeof(struct Closure)))) {
|
||||||
|
Error(6, "OUT OF HEAP");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frep = t->next;
|
||||||
|
t->refs = 1;
|
||||||
|
++heap;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pushes continuation for argument
|
||||||
|
void App(void) {
|
||||||
|
int x = mem[ip + 1];
|
||||||
|
struct Closure *t = Alloc();
|
||||||
|
t->term = ip + 2 + x;
|
||||||
|
t->envp = t->term > 21 && t->term != end ? REF(envp) : &root;
|
||||||
|
t->next = contp;
|
||||||
|
contp = t;
|
||||||
|
ip += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LoadByte(int c) {
|
||||||
|
int i, r = end;
|
||||||
|
for (i = 7; i >= 0; --i) {
|
||||||
|
Expand(ABS);
|
||||||
|
Expand(APP);
|
||||||
|
Expand(i ? +4 : Backref(NIL));
|
||||||
|
Expand(APP);
|
||||||
|
Expand(Backref(c & (1 << i) ? FALSE : TRUE));
|
||||||
|
Expand(VAR);
|
||||||
|
Expand(0);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRom(void) {
|
||||||
|
long i;
|
||||||
|
for (; end < sizeof(kRom) / sizeof(*kRom); ++end) {
|
||||||
|
mem[end] = kRom[end];
|
||||||
|
}
|
||||||
|
mem[4] = binary ? 2 : 9;
|
||||||
|
if (binary) {
|
||||||
|
for (i = 0; i < 256; ++i) {
|
||||||
|
kLazy[i] = LoadByte(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mem[1] = end - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Iop(void) {
|
||||||
|
if (ip == end) {
|
||||||
|
Gro();
|
||||||
|
} else {
|
||||||
|
Put(); // ip ∈ {6,13,20,21}
|
||||||
|
}
|
||||||
|
Gc(envp);
|
||||||
|
envp = &root;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Rex(void) {
|
||||||
|
if (slog) PrintMachineState(stderr);
|
||||||
|
if (rlog && (alog || mem[ip] != APP)) {
|
||||||
|
PrintExpressions(stderr, alog, vlog);
|
||||||
|
}
|
||||||
|
switch (mem[ip]) {
|
||||||
|
case VAR:
|
||||||
|
Var();
|
||||||
|
break;
|
||||||
|
case APP:
|
||||||
|
App();
|
||||||
|
break;
|
||||||
|
case ABS:
|
||||||
|
Abs();
|
||||||
|
break;
|
||||||
|
case IOP:
|
||||||
|
Iop();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error(7, "CORRUPT TERM");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Krivine(void) {
|
||||||
|
int main;
|
||||||
|
long gotoget;
|
||||||
|
LoadRom();
|
||||||
|
mem[end++] = APP;
|
||||||
|
gotoget = end++;
|
||||||
|
main = end;
|
||||||
|
mem[gotoget] = Parse(1, stdin).n;
|
||||||
|
if (rlog) {
|
||||||
|
Print(main, 1, 0, stderr);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
if (alog) {
|
||||||
|
fputs("⟿ wrap[", stderr);
|
||||||
|
Print(0, 1, 0, stderr);
|
||||||
|
fputs("]\n", stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (;;) Rex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadFlags(int argc, char *argv[]) {
|
||||||
|
int i;
|
||||||
|
const char *prog;
|
||||||
|
prog = argc ? argv[0] : "cblc";
|
||||||
|
while ((i = getopt(argc, argv, "?hubBdsarvnNlS")) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case 'b':
|
||||||
|
binary = 1;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
safer = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
noname = 1;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
asciiname = 1;
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
style = 2;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
style = 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
slog = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rlog = 1;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
rlog = 1;
|
||||||
|
alog = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
rlog = 1;
|
||||||
|
vlog = 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
postdump = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
case 'h':
|
||||||
|
PrintUsage(prog, 0, stdout);
|
||||||
|
default:
|
||||||
|
PrintUsage(prog, 1, stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct rlimit rlim = {512 * 1024 * 1024, 512 * 1024 * 1024};
|
||||||
|
setrlimit(RLIMIT_AS, &rlim);
|
||||||
|
signal(SIGQUIT, Quit);
|
||||||
|
signal(SIGPIPE, Quit);
|
||||||
|
LoadFlags(argc, argv);
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
setvbuf(stdout, 0, _IOLBF, 0);
|
||||||
|
setvbuf(stderr, 0, _IOLBF, 0);
|
||||||
|
Krivine();
|
||||||
|
}
|
59
tool/lambda/lambda.mk
Normal file
59
tool/lambda/lambda.mk
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
|
||||||
|
PKGS += TOOL_LAMBDA
|
||||||
|
|
||||||
|
TOOL_LAMBDA_SRCS := $(wildcard tool/lambda/*.c)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_OBJS = \
|
||||||
|
$(TOOL_LAMBDA_SRCS:%.c=o/$(MODE)/%.o)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_COMS := \
|
||||||
|
$(TOOL_LAMBDA_SRCS:%.c=o/$(MODE)/%.com)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_BINS = \
|
||||||
|
$(TOOL_LAMBDA_COMS) \
|
||||||
|
$(TOOL_LAMBDA_COMS:%=%.dbg)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_DIRECTDEPS = \
|
||||||
|
LIBC_INTRIN \
|
||||||
|
LIBC_LOG \
|
||||||
|
LIBC_MEM \
|
||||||
|
LIBC_CALLS \
|
||||||
|
LIBC_RUNTIME \
|
||||||
|
LIBC_UNICODE \
|
||||||
|
LIBC_FMT \
|
||||||
|
LIBC_STR \
|
||||||
|
LIBC_SYSV \
|
||||||
|
LIBC_STDIO \
|
||||||
|
LIBC_X \
|
||||||
|
LIBC_STUBS \
|
||||||
|
LIBC_NEXGEN32E \
|
||||||
|
TOOL_LAMBDA_LIB \
|
||||||
|
THIRD_PARTY_GETOPT
|
||||||
|
|
||||||
|
TOOL_LAMBDA_DEPS := \
|
||||||
|
$(call uniq,$(foreach x,$(TOOL_LAMBDA_DIRECTDEPS),$($(x))))
|
||||||
|
|
||||||
|
o/$(MODE)/tool/lambda/lambda.pkg: \
|
||||||
|
$(TOOL_LAMBDA_OBJS) \
|
||||||
|
$(foreach x,$(TOOL_LAMBDA_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
o/$(MODE)/tool/lambda/%.com.dbg: \
|
||||||
|
$(TOOL_LAMBDA_DEPS) \
|
||||||
|
o/$(MODE)/tool/lambda/%.o \
|
||||||
|
o/$(MODE)/tool/lambda/lambda.pkg \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE)
|
||||||
|
@$(APELINK)
|
||||||
|
|
||||||
|
o/$(MODE)/tool/lambda/tromp.o: \
|
||||||
|
OVERRIDE_CFLAGS += \
|
||||||
|
-w
|
||||||
|
|
||||||
|
$(TOOL_LAMBDA_OBJS): \
|
||||||
|
$(BUILD_FILES) \
|
||||||
|
tool/lambda/lambda.mk
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/tool/lambda
|
||||||
|
o/$(MODE)/tool/lambda: $(TOOL_LAMBDA_BINS) $(TOOL_LAMBDA_CHECKS)
|
65
tool/lambda/lib/blc.h
Normal file
65
tool/lambda/lib/blc.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef COSMOPOLITAN_TOOL_LAMBDA_LIB_BLC_H_
|
||||||
|
#define COSMOPOLITAN_TOOL_LAMBDA_LIB_BLC_H_
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
#define BUILTINS 4
|
||||||
|
#define LOC 12
|
||||||
|
#define TERMS 5000000
|
||||||
|
|
||||||
|
#define IOP 0 // code for gro, wr0, wr1, put
|
||||||
|
#define VAR 1 // code for variable lookup
|
||||||
|
#define APP 2 // code for applications
|
||||||
|
#define ABS 3 // code for abstractions
|
||||||
|
|
||||||
|
struct Parse {
|
||||||
|
int n;
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Closure {
|
||||||
|
struct Closure *next;
|
||||||
|
struct Closure *envp;
|
||||||
|
int refs;
|
||||||
|
int term;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern char vlog;
|
||||||
|
extern char slog;
|
||||||
|
extern char alog;
|
||||||
|
extern char rlog;
|
||||||
|
extern char safer;
|
||||||
|
extern char style;
|
||||||
|
extern char binary;
|
||||||
|
extern char noname;
|
||||||
|
extern char asciiname;
|
||||||
|
extern int ci;
|
||||||
|
extern int co;
|
||||||
|
extern long ip;
|
||||||
|
extern long end;
|
||||||
|
extern int heap;
|
||||||
|
extern FILE *logh;
|
||||||
|
extern int mem[TERMS];
|
||||||
|
extern struct Closure root;
|
||||||
|
extern struct Closure *envp;
|
||||||
|
extern struct Closure *frep;
|
||||||
|
extern struct Closure *contp;
|
||||||
|
|
||||||
|
char GetBit(FILE *);
|
||||||
|
char NeedBit(FILE *);
|
||||||
|
struct Parse Parse(int, FILE *);
|
||||||
|
void Dump(int, int, FILE *);
|
||||||
|
void Error(int, const char *, ...);
|
||||||
|
void PrintLambda(int, int, int, int, FILE *);
|
||||||
|
void PrintBinary(int, int, int, FILE *);
|
||||||
|
void PrintDebruijn(int, int, int, FILE *);
|
||||||
|
void PrintMachineState(FILE *);
|
||||||
|
void PrintExpressions(FILE *, char, char);
|
||||||
|
void Print(int, int, int, FILE *);
|
||||||
|
void PrintVar(int, FILE *);
|
||||||
|
void *Calloc(size_t, size_t);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_TOOL_LAMBDA_LIB_BLC_H_ */
|
43
tool/lambda/lib/calloc.c
Normal file
43
tool/lambda/lib/calloc.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/sysv/consts/map.h"
|
||||||
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
||||||
|
void *Calloc(size_t a, size_t b) {
|
||||||
|
char *r;
|
||||||
|
size_t z;
|
||||||
|
static char *p;
|
||||||
|
static size_t i;
|
||||||
|
static size_t n;
|
||||||
|
z = a * b;
|
||||||
|
if (!p) {
|
||||||
|
n = FRAMESIZE;
|
||||||
|
p = mmap((void *)0x300000000000, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||||
|
}
|
||||||
|
if (i + z > n) {
|
||||||
|
mmap(p + i, FRAMESIZE, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||||
|
n += FRAMESIZE;
|
||||||
|
}
|
||||||
|
r = p + i;
|
||||||
|
i += z;
|
||||||
|
return r;
|
||||||
|
}
|
154
tool/lambda/lib/debug.c
Normal file
154
tool/lambda/lib/debug.c
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
const char *GetOpName(int x) {
|
||||||
|
switch (x) {
|
||||||
|
case VAR:
|
||||||
|
return "var";
|
||||||
|
case APP:
|
||||||
|
return "app";
|
||||||
|
case ABS:
|
||||||
|
return "abs";
|
||||||
|
case IOP:
|
||||||
|
return "iop";
|
||||||
|
default:
|
||||||
|
return "wut";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetDepth(struct Closure *env) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; env && env != &root; ++i) {
|
||||||
|
env = env->next;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintClosure(struct Closure *c, const char *name, int indent, FILE *f) {
|
||||||
|
int i, j;
|
||||||
|
char ibuf[21];
|
||||||
|
while (c && c != &root) {
|
||||||
|
for (j = 0; j < indent; ++j) {
|
||||||
|
if (j) {
|
||||||
|
fputs("│ ", f);
|
||||||
|
} else {
|
||||||
|
fputs(" ", f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputs(name, f);
|
||||||
|
fputs(": ", f);
|
||||||
|
Print(c->term, 0, GetDepth(c->envp), f);
|
||||||
|
fputs(" +", f);
|
||||||
|
int64toarray_radix10(c->refs, ibuf);
|
||||||
|
fputs(ibuf, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
PrintClosure(c->envp, "envp", indent + 1, f);
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintMachineState(FILE *f) {
|
||||||
|
int i;
|
||||||
|
char buf[256];
|
||||||
|
static int op;
|
||||||
|
struct Closure *c;
|
||||||
|
fputc('\n', f);
|
||||||
|
for (i = 0; i < 80; ++i) fputwc(L'─', f);
|
||||||
|
ksnprintf(buf, sizeof(buf),
|
||||||
|
"%d\n ip %ld | op %d %s | arg %d | end %ld\n", op++, ip,
|
||||||
|
mem[ip], GetOpName(mem[ip]), mem[ip + 1], end);
|
||||||
|
fputs(buf, f);
|
||||||
|
fputs(" term ", f);
|
||||||
|
Print(ip, 0, GetDepth(envp), f);
|
||||||
|
fputc('\n', f);
|
||||||
|
fputc('\n', f);
|
||||||
|
PrintClosure(contp, "contp", 1, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
PrintClosure(envp, "envp", 1, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
PrintClosure(frep, "frep", 1, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintExpressions(FILE *f, char alog, char vlog) {
|
||||||
|
int i, d;
|
||||||
|
char buf[48];
|
||||||
|
struct Closure *p, ps;
|
||||||
|
ps.term = ip;
|
||||||
|
ps.next = contp;
|
||||||
|
ps.envp = envp;
|
||||||
|
for (p = &ps; p; p = p->next) {
|
||||||
|
Print(p->term, 1, GetDepth(p->envp), f);
|
||||||
|
if (p->next) fputc(' ', f);
|
||||||
|
}
|
||||||
|
if (alog) {
|
||||||
|
fputs(" ⟹ ", f);
|
||||||
|
switch (mem[ip]) {
|
||||||
|
case VAR:
|
||||||
|
ksnprintf(buf, sizeof(buf), "var[%d]", mem[ip + 1]);
|
||||||
|
fputs(buf, f);
|
||||||
|
break;
|
||||||
|
case APP:
|
||||||
|
fputs("app[", f);
|
||||||
|
Print(ip + 2 + mem[ip + 1], 1, GetDepth(envp), f);
|
||||||
|
fputc(']', f);
|
||||||
|
break;
|
||||||
|
case ABS:
|
||||||
|
if (contp) {
|
||||||
|
fputs("abs[", f);
|
||||||
|
Print(ip + 1, 1, GetDepth(envp), f);
|
||||||
|
fputc(']', f);
|
||||||
|
} else {
|
||||||
|
ksnprintf(buf, sizeof(buf), "bye[%d]", mem[ip + 2]);
|
||||||
|
fputs(buf, f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IOP:
|
||||||
|
if (ip < 22) {
|
||||||
|
if (!binary) {
|
||||||
|
ksnprintf(buf, sizeof(buf), "put[%c]", '0' + (int)(ip & 1));
|
||||||
|
} else if (mem[ip + 1] & 1) {
|
||||||
|
ksnprintf(buf, sizeof(buf), "put[0%hho '%c']", co,
|
||||||
|
isprint(co) ? co : '.');
|
||||||
|
} else {
|
||||||
|
ksnprintf(buf, sizeof(buf), "wr%d[0%hho]", (int)(ip & 1), co);
|
||||||
|
}
|
||||||
|
fputs(buf, f);
|
||||||
|
} else {
|
||||||
|
fputs("gro", f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vlog) {
|
||||||
|
d = GetDepth(envp);
|
||||||
|
for (i = 0, p = envp; p->term != -1; ++i, p = p->next) {
|
||||||
|
fputc('\n', f);
|
||||||
|
fputc('\t', f);
|
||||||
|
PrintVar(style != 1 ? i : d - 1 - i, f);
|
||||||
|
fputc('=', f);
|
||||||
|
Print(p->term, 0, GetDepth(p), f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputc('\n', f);
|
||||||
|
}
|
63
tool/lambda/lib/dump.c
Normal file
63
tool/lambda/lib/dump.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
void Dumper(int i, int j, FILE *f) {
|
||||||
|
char buf[64];
|
||||||
|
if (i) fputc('\n', f);
|
||||||
|
for (; i < j; ++i) {
|
||||||
|
switch (mem[i]) {
|
||||||
|
case VAR:
|
||||||
|
ksnprintf(buf, sizeof(buf), " %s,%d,\t// %2d: ", "VAR", mem[i + 1],
|
||||||
|
i);
|
||||||
|
fputs(buf, f);
|
||||||
|
Print(i, 1, 0, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
|
case APP:
|
||||||
|
ksnprintf(buf, sizeof(buf), " %s,%d,\t// %2d: ", "APP", mem[i + 1],
|
||||||
|
i);
|
||||||
|
fputs(buf, f);
|
||||||
|
Print(i, 1, 0, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
++i;
|
||||||
|
break;
|
||||||
|
case ABS:
|
||||||
|
ksnprintf(buf, sizeof(buf), " %s,\t// %2d: ", "ABS", i);
|
||||||
|
fputs(buf, f);
|
||||||
|
Print(i, 1, 0, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ksnprintf(buf, sizeof(buf), " %d,\t// %2d: ", mem[i], i);
|
||||||
|
fputs(buf, f);
|
||||||
|
Print(i, 1, 0, f);
|
||||||
|
fputc('\n', f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dump(int i, int j, FILE *f) {
|
||||||
|
fputs("\nstatic int kTerm[] = {\n", f);
|
||||||
|
Dumper(i, j, f);
|
||||||
|
fputs("};\n", f);
|
||||||
|
}
|
37
tool/lambda/lib/error.c
Normal file
37
tool/lambda/lib/error.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
void Error(int rc, const char* s, ...) {
|
||||||
|
va_list va;
|
||||||
|
fflush(stdout);
|
||||||
|
fputs("\n\33[1;31mERROR\33[37m:\t", stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
va_start(va, s);
|
||||||
|
kvprintf(s, va);
|
||||||
|
va_end(va);
|
||||||
|
fputs("\33[0m\n", stderr);
|
||||||
|
kprintf(" ip:\t%ld\n", ip);
|
||||||
|
kprintf(" end:\t%ld\n", end);
|
||||||
|
kprintf(" term:\t");
|
||||||
|
PrintExpressions(stderr, 0, 1);
|
||||||
|
/* Dump(0, end, stderr); */
|
||||||
|
exit(rc);
|
||||||
|
}
|
54
tool/lambda/lib/getbit.c
Normal file
54
tool/lambda/lib/getbit.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
char GetBit(FILE* f) {
|
||||||
|
wint_t c;
|
||||||
|
char comment;
|
||||||
|
static wint_t buf, mask;
|
||||||
|
if (!binary) {
|
||||||
|
for (comment = 0;;) {
|
||||||
|
c = fgetwc(f);
|
||||||
|
if (c == -1) break;
|
||||||
|
if (!comment) {
|
||||||
|
fflush(stdout);
|
||||||
|
if (c == ';') {
|
||||||
|
comment = 1;
|
||||||
|
} else if (!iswspace(c) && c != '(' && c != ')' && c != '[' &&
|
||||||
|
c != ']') {
|
||||||
|
if (c != -1) c &= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (c == '\n') {
|
||||||
|
comment = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (mask) {
|
||||||
|
c = !!(buf & mask);
|
||||||
|
mask >>= 1;
|
||||||
|
} else {
|
||||||
|
c = fgetc(f);
|
||||||
|
if (c != -1) {
|
||||||
|
buf = c;
|
||||||
|
c = (c >> 7) & 1;
|
||||||
|
mask = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
65
tool/lambda/lib/lib.mk
Normal file
65
tool/lambda/lib/lib.mk
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
|
||||||
|
PKGS += TOOL_LAMBDA_LIB
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_ARTIFACTS += TOOL_LAMBDA_LIB_A
|
||||||
|
TOOL_LAMBDA_LIB = $(TOOL_LAMBDA_LIB_A_DEPS) $(TOOL_LAMBDA_LIB_A)
|
||||||
|
TOOL_LAMBDA_LIB_A = o/$(MODE)/tool/lambda/lib/lambdalib.a
|
||||||
|
TOOL_LAMBDA_LIB_A_FILES := $(filter-out %/.%,$(wildcard tool/lambda/lib/*))
|
||||||
|
TOOL_LAMBDA_LIB_A_HDRS = $(filter %.h,$(TOOL_LAMBDA_LIB_A_FILES))
|
||||||
|
TOOL_LAMBDA_LIB_A_SRCS_S = $(filter %.S,$(TOOL_LAMBDA_LIB_A_FILES))
|
||||||
|
TOOL_LAMBDA_LIB_A_SRCS_C = $(filter %.c,$(TOOL_LAMBDA_LIB_A_FILES))
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_A_CHECKS = \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_HDRS:%=o/$(MODE)/%.ok) \
|
||||||
|
$(TOOL_LAMBDA_LIB_A).pkg
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_A_SRCS = \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_SRCS_S) \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_SRCS_C)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_A_OBJS = \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_A_DIRECTDEPS = \
|
||||||
|
LIBC_BITS \
|
||||||
|
LIBC_CALLS \
|
||||||
|
LIBC_INTRIN \
|
||||||
|
LIBC_LOG \
|
||||||
|
LIBC_NEXGEN32E \
|
||||||
|
LIBC_RAND \
|
||||||
|
LIBC_RUNTIME \
|
||||||
|
LIBC_UNICODE \
|
||||||
|
LIBC_MEM \
|
||||||
|
LIBC_FMT \
|
||||||
|
LIBC_SOCK \
|
||||||
|
LIBC_STDIO \
|
||||||
|
LIBC_STR \
|
||||||
|
LIBC_STUBS \
|
||||||
|
LIBC_SYSV \
|
||||||
|
THIRD_PARTY_COMPILER_RT \
|
||||||
|
THIRD_PARTY_GETOPT
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_A_DEPS := \
|
||||||
|
$(call uniq,$(foreach x,$(TOOL_LAMBDA_LIB_A_DIRECTDEPS),$($(x))))
|
||||||
|
|
||||||
|
$(TOOL_LAMBDA_LIB_A): \
|
||||||
|
$(TOOL_LAMBDA_LIB_A).pkg \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_OBJS)
|
||||||
|
|
||||||
|
$(TOOL_LAMBDA_LIB_A).pkg: \
|
||||||
|
$(TOOL_LAMBDA_LIB_A_OBJS) \
|
||||||
|
$(foreach x,$(TOOL_LAMBDA_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
TOOL_LAMBDA_LIB_LIBS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)))
|
||||||
|
TOOL_LAMBDA_LIB_SRCS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
TOOL_LAMBDA_LIB_HDRS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||||
|
TOOL_LAMBDA_LIB_BINS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_BINS))
|
||||||
|
TOOL_LAMBDA_LIB_CHECKS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_CHECKS))
|
||||||
|
TOOL_LAMBDA_LIB_OBJS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_OBJS))
|
||||||
|
TOOL_LAMBDA_LIB_TESTS = $(foreach x,$(TOOL_LAMBDA_LIB_ARTIFACTS),$($(x)_TESTS))
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/tool/lambda/lib
|
||||||
|
o/$(MODE)/tool/lambda/lib: $(TOOL_LAMBDA_LIB_CHECKS)
|
25
tool/lambda/lib/needbit.c
Normal file
25
tool/lambda/lib/needbit.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
char NeedBit(FILE* f) {
|
||||||
|
char b = GetBit(f);
|
||||||
|
if (b == -1) Error(9, "UNEXPECTED EOF");
|
||||||
|
return b;
|
||||||
|
}
|
55
tool/lambda/lib/parse.c
Normal file
55
tool/lambda/lib/parse.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses binary lambda calculus closed expression from stream.
|
||||||
|
*/
|
||||||
|
struct Parse Parse(int ignored, FILE* f) {
|
||||||
|
int t, start;
|
||||||
|
char bit, need;
|
||||||
|
struct Parse p;
|
||||||
|
for (need = 0, start = end;;) {
|
||||||
|
if (end + 2 > TERMS) Error(5, "OUT OF TERMS");
|
||||||
|
if ((bit = GetBit(f)) == -1) {
|
||||||
|
if (!need) break;
|
||||||
|
fflush(stdout);
|
||||||
|
fputs("---\n", stderr);
|
||||||
|
Print(start, 0, 0, stderr);
|
||||||
|
Error(9, "UNFINISHED EXPRESSION");
|
||||||
|
} else if (bit) {
|
||||||
|
for (t = 0; NeedBit(f);) ++t;
|
||||||
|
mem[end++] = VAR;
|
||||||
|
mem[end++] = t;
|
||||||
|
break;
|
||||||
|
} else if (NeedBit(f)) {
|
||||||
|
t = end;
|
||||||
|
end += 2;
|
||||||
|
mem[t] = APP;
|
||||||
|
p = Parse(0, f);
|
||||||
|
mem[t + 1] = p.n;
|
||||||
|
need = 1;
|
||||||
|
} else {
|
||||||
|
mem[end++] = ABS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.i = start;
|
||||||
|
p.n = end - start;
|
||||||
|
return p;
|
||||||
|
}
|
72
tool/lambda/lib/parserom.c
Normal file
72
tool/lambda/lib/parserom.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
static struct Parse ParseImpl(int tail, int need, FILE *f) {
|
||||||
|
struct Parse p, q;
|
||||||
|
int b, i, j, t, start;
|
||||||
|
for (start = end;;) {
|
||||||
|
if (end + 2 > TERMS) Error(5, "OUT OF TERMS");
|
||||||
|
if ((b = GetBit(f)) == -1) {
|
||||||
|
if (need) Error(9, "UNFINISHED EXPRESSION");
|
||||||
|
break;
|
||||||
|
} else if (b) {
|
||||||
|
for (t = 0; NeedBit(f);) ++t;
|
||||||
|
mem[end++] = VAR;
|
||||||
|
mem[end++] = t;
|
||||||
|
break;
|
||||||
|
} else if (NeedBit(f)) {
|
||||||
|
t = end;
|
||||||
|
end += 2;
|
||||||
|
p = ParseImpl(0, 1, f);
|
||||||
|
q = ParseImpl(t + 2, 1, f);
|
||||||
|
mem[t + 0] = APP;
|
||||||
|
mem[t + 1] = q.i - (t + 2);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
mem[end++] = ABS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.i = start;
|
||||||
|
p.n = end - start;
|
||||||
|
if (p.n && tail) {
|
||||||
|
/* find backwards overlaps within 8-bit displacement */
|
||||||
|
i = tail - 32768;
|
||||||
|
j = start - p.n;
|
||||||
|
for (i = i < 0 ? 0 : i; i <= j; ++i) {
|
||||||
|
if (!memcmp(mem + i, mem + p.i, p.n * sizeof(*mem))) {
|
||||||
|
memset(mem + start, -1, p.n * sizeof(*mem));
|
||||||
|
end = start;
|
||||||
|
p.i = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses binary lambda calculus closed expression from stream.
|
||||||
|
*
|
||||||
|
* If `tail` is non-zero then this subroutine will perform expensive
|
||||||
|
* deduplication so that optimal ROMs may be computed ahead of time.
|
||||||
|
*/
|
||||||
|
struct Parse Parse(int tail, FILE *f) {
|
||||||
|
return ParseImpl(tail, 0, f);
|
||||||
|
}
|
1289
tool/lambda/lib/print.c
Normal file
1289
tool/lambda/lib/print.c
Normal file
File diff suppressed because it is too large
Load diff
40
tool/lambda/lib/vars.c
Normal file
40
tool/lambda/lib/vars.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
char binary; // 8-bit
|
||||||
|
char safer; // safer
|
||||||
|
char style; // notation
|
||||||
|
char asciiname; // <3 ascii
|
||||||
|
char noname; // rewriting
|
||||||
|
char rlog; // redex log
|
||||||
|
char slog; // state log
|
||||||
|
char alog; // action log
|
||||||
|
char vlog; // variable log
|
||||||
|
int co; // output character
|
||||||
|
int heap; // heap usage counter
|
||||||
|
long ip; // instruction pointer
|
||||||
|
long end; // end of code pointer
|
||||||
|
FILE *logh; // log file stdio stream
|
||||||
|
struct Closure *frep; // freed closures list
|
||||||
|
struct Closure *contp; // continuations stack
|
||||||
|
int mem[TERMS]; // bss memory for terms
|
||||||
|
|
||||||
|
struct Closure root = {.refs = 100000, .term = -1, .next = 0};
|
||||||
|
struct Closure *envp = &root;
|
37
tool/lambda/tromp.c
Normal file
37
tool/lambda/tromp.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Public Domain
|
||||||
|
// Author: John Tromp
|
||||||
|
// Source: IOCCC 2012
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "tool/lambda/lib/blc.h"
|
||||||
|
|
||||||
|
#define A 500000
|
||||||
|
#define X 8
|
||||||
|
#define Int long
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
Int L[A],m,b,*D=A,
|
||||||
|
*c,*a=L,C,*U=L,u;s
|
||||||
|
(_){u--&&s(a=*a);}
|
||||||
|
char*B,I,O;S(){b=b
|
||||||
|
--?b:m|read(0,&I,1
|
||||||
|
)-1;return~I>>b&1;
|
||||||
|
}k(l,u){for(;l<=u;
|
||||||
|
U-L<A?*U++=46^l++[
|
||||||
|
"-,&,,/.--/,:-,'/"
|
||||||
|
".-,-,,/.-,*,//..,"
|
||||||
|
]:exit(5));}p(Int*m){
|
||||||
|
return!*U?*m=S()?U++,!S
|
||||||
|
()?m[1]=p(++U),2:3:1,p(U)
|
||||||
|
:S()?U+=2:p(U[1]++),U-m;}x(
|
||||||
|
c){k(7*!b,9);*U++=b&&S();c&&x
|
||||||
|
(b);}d(Int*l){--l[1]||d(l[d(*l),
|
||||||
|
*l=B,B=l,2]);}main(e){for(k(10,33
|
||||||
|
),a[4]-=m=e-2&7,a[23]=p(U),b=0;;e-2
|
||||||
|
?e?e-3?s(D=a),C=a [3],++1[a=a[2]],d(
|
||||||
|
D):c?D=c,c=*D,*D= a,a=D:exit(L[C+1])
|
||||||
|
:C--<23?C=u+m&1?O =O+O|C&1,9:write(m
|
||||||
|
||(O=C+28),&O,1)+ 1:(S(),x(0<b++?k(0,
|
||||||
|
6),U[-5]=96:0)):( D=B?B:Calloc(4,X))
|
||||||
|
?B=*D,*D=c,c=D,D[ 2]=a,a[++D[1]]++,D
|
||||||
|
[3]=++C+u:exit(6) )e=L[C++],u=L[C];}
|
|
@ -6,5 +6,6 @@ o/$(MODE)/tool: \
|
||||||
o/$(MODE)/tool/build \
|
o/$(MODE)/tool/build \
|
||||||
o/$(MODE)/tool/decode \
|
o/$(MODE)/tool/decode \
|
||||||
o/$(MODE)/tool/hash \
|
o/$(MODE)/tool/hash \
|
||||||
|
o/$(MODE)/tool/lambda \
|
||||||
o/$(MODE)/tool/net \
|
o/$(MODE)/tool/net \
|
||||||
o/$(MODE)/tool/viz
|
o/$(MODE)/tool/viz
|
||||||
|
|
Loading…
Reference in a new issue