about summary refs log tree commit diff stats
path: root/html/schemer
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-09-07 20:31:40 -0400
committerelioat <elioat@tilde.institute>2024-09-07 20:31:40 -0400
commite59ea3378b22261765f61ee8597bd2b7238cb98a (patch)
tree57b4e9ca2c34d68f9c646d1c11ea9a9784970eb5 /html/schemer
parentda6be82d03a94c46069b9a04cb6b61cfe355eaf4 (diff)
downloadtour-e59ea3378b22261765f61ee8597bd2b7238cb98a.tar.gz
*
Diffstat (limited to 'html/schemer')
-rw-r--r--html/schemer/index.html233
-rw-r--r--html/schemer/tls.pdfbin0 -> 2359953 bytes
2 files changed, 233 insertions, 0 deletions
diff --git a/html/schemer/index.html b/html/schemer/index.html
new file mode 100644
index 0000000..ebadf83
--- /dev/null
+++ b/html/schemer/index.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Scheme Interpreter with PDF</title>
+    <style>
+        body, html {
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            font-family: Arial, sans-serif;
+        }
+        #pdf-container {
+            width: 100%;
+            height: 67%;
+            overflow: hidden;
+        }
+        #repl-container {
+            width: 100%;
+            height: 33%;
+            display: flex;
+            flex-direction: column;
+            border-top: 1px solid #ccc;
+            padding: 10px;
+        }
+        textarea {
+            flex: 1;
+            width: 100%;
+            font-family: monospace;
+            font-size: 16px;
+            padding: 10px;
+        }
+        button {
+            margin-top: 10px;
+            padding: 10px;
+            font-size: 16px;
+        }
+        #scheme-output {
+            font-family: monospace;
+            background-color: #f0f0f0;
+            padding: 10px;
+            margin-top: 10px;
+            overflow-wrap: break-word;
+        }
+    </style>
+</head>
+<body>
+
+    <div id="pdf-container">
+        <embed src="tls.pdf" type="application/pdf" width="100%" height="100%">
+    </div>
+
+    <div id="repl-container">
+        <textarea id="scheme-input" placeholder="Scheme here..."></textarea>
+        <div id="scheme-output"></div>
+        <button onclick="evaluateScheme()">Run Code</button>
+    </div>
+
+    <script>
+        // Scheme interpreter (unchanged)
+        function tokenizeScheme(input) {
+            const tokens = [];
+            let current = 0;
+
+            const isWhitespace = (char) => /\s/.test(char);
+            const isDigit = (char) => /[0-9]/.test(char);
+            const isParen = (char) => char === '(' || char === ')';
+            const isSymbolChar = (char) => /[a-zA-Z0-9\+\-\*\/\=\?\!\_]/.test(char);
+
+            while (current < input.length) {
+                let char = input[current];
+
+                if (isWhitespace(char)) {
+                    current++;
+                    continue;
+                }
+
+                if (isParen(char)) {
+                    tokens.push({ type: 'paren', value: char });
+                    current++;
+                    continue;
+                }
+
+                if (isDigit(char) || (char === '-' && isDigit(input[current + 1]))) {
+                    let number = '';
+                    while (isDigit(char) || char === '-') {
+                        number += char;
+                        char = input[++current];
+                    }
+                    tokens.push({ type: 'number', value: number });
+                    continue;
+                }
+
+                if (isSymbolChar(char)) {
+                    let symbol = '';
+                    while (isSymbolChar(char)) {
+                        symbol += char;
+                        char = input[++current];
+                    }
+                    tokens.push({ type: 'symbol', value: symbol });
+                    continue;
+                }
+
+                throw new Error(`Unexpected character: ${char}`);
+            }
+
+            return tokens;
+        }
+
+        function parseScheme(tokens) {
+            let current = 0;
+
+            function walk() {
+                let token = tokens[current];
+
+                if (token.type === 'number') {
+                    current++;
+                    return { type: 'NumberLiteral', value: Number(token.value) };
+                }
+
+                if (token.type === 'symbol') {
+                    current++;
+                    return { type: 'Symbol', value: token.value };
+                }
+
+                if (token.type === 'paren' && token.value === '(') {
+                    current++;
+                    const node = { type: 'List', value: [] };
+
+                    while (!(tokens[current].type === 'paren' && tokens[current].value === ')')) {
+                        node.value.push(walk());
+                    }
+
+                    current++; // Skip closing ')'
+                    return node;
+                }
+
+                throw new Error(`Unexpected token: ${token.type}`);
+            }
+
+            return walk();
+        }
+
+        const globalEnv = {
+            '+': (...args) => args.reduce((acc, curr) => acc + curr),
+            '-': (...args) => args.reduce((acc, curr) => acc - curr),
+            '*': (...args) => args.reduce((acc, curr) => acc * curr),
+            '/': (a, b) => a / b,
+            'eq?': (...args) => args.every((val, i, arr) => val === arr[0]),
+            'car': (list) => list[0],
+            'cdr': (list) => list.slice(1),
+            'cons': (a, b) => [a].concat(b),
+            'null?': (list) => list.length === 0,
+        };
+
+        function evaluate(node, env = globalEnv) {
+            if (node.type === 'NumberLiteral') {
+                return node.value;
+            }
+
+            if (node.type === 'Symbol') {
+                if (env[node.value] !== undefined) {
+                    return env[node.value];
+                }
+                throw new Error(`Undefined symbol: ${node.value}`);
+            }
+
+            if (node.type === 'List') {
+                const [first, ...rest] = node.value;
+
+                if (first.type === 'Symbol') {
+                    const operator = first.value;
+
+                    if (operator === 'define') {
+                        const [symbol, expr] = rest;
+                        env[symbol.value] = evaluate(expr, env);
+                        return;
+                    }
+
+                    if (operator === 'lambda') {
+                        const [params, body] = rest;
+
+                        return function (...args) {
+                            const lambdaEnv = { ...env };
+                            params.value.forEach((param, i) => {
+                                lambdaEnv[param.value] = args[i];
+                            });
+                            return evaluate(body, lambdaEnv);
+                        };
+                    }
+
+                    if (operator === 'if') {
+                        const [test, consequent, alternate] = rest;
+                        const condition = evaluate(test, env);
+                        return condition ? evaluate(consequent, env) : evaluate(alternate, env);
+                    }
+                }
+
+                const func = evaluate(first, env);
+
+                if (typeof func !== 'function') {
+                    throw new Error(`Expected a function but got: ${func}`);
+                }
+
+                const args = rest.map(arg => evaluate(arg, env));
+                return func(...args);
+            }
+
+            throw new Error(`Unexpected node type: ${node.type}`);
+        }
+
+        function evalScheme(input) {
+            const tokens = tokenizeScheme(input);
+            const ast = parseScheme(tokens);
+            return evaluate(ast);
+        }
+
+        // Function to evaluate the input in the REPL
+        function evaluateScheme() {
+            const input = document.getElementById('scheme-input').value;
+            let output;
+            try {
+                output = evalScheme(input);
+            } catch (error) {
+                output = `Error: ${error.message}`;
+            }
+            document.getElementById('scheme-output').innerText = JSON.stringify(output, null, 2);
+        }
+    </script>
+
+</body>
+</html>
diff --git a/html/schemer/tls.pdf b/html/schemer/tls.pdf
new file mode 100644
index 0000000..7e28a5f
--- /dev/null
+++ b/html/schemer/tls.pdf
Binary files differ