Working assignment, reader macros, mexpr interpretation.
This commit is contained in:
parent
b5e418118b
commit
6a8417a367
|
@ -89,9 +89,9 @@ Intended deviations from the behaviour of the real Lisp reader are as follows:
|
||||||
1. It reads the meta-expression language `MEXPR` in addition to the
|
1. It reads the meta-expression language `MEXPR` in addition to the
|
||||||
symbolic expression language `SEXPR`, which I do not believe the Lisp 1.5
|
symbolic expression language `SEXPR`, which I do not believe the Lisp 1.5
|
||||||
reader ever did;
|
reader ever did;
|
||||||
2. It treats everything between a semi-colon and an end of line as a comment,
|
2. It treats everything between a double semi-colon and an end of line as
|
||||||
as most modern Lisps do; but I do not believe Lisp 1.5 had this feature.
|
a comment, as most modern Lisps do; but I do not believe Lisp 1.5 had
|
||||||
|
this feature.
|
||||||
|
|
||||||
### BUT WHY?!!?!
|
### BUT WHY?!!?!
|
||||||
|
|
||||||
|
@ -116,7 +116,6 @@ implementations. I'm convinced you could still use Lisp 1.5 for interesting
|
||||||
and useful software (which isn't to say that some modern Lisps aren't better,
|
and useful software (which isn't to say that some modern Lisps aren't better,
|
||||||
but this is software which is almost sixty years old).
|
but this is software which is almost sixty years old).
|
||||||
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
At present, clone the source and build it using
|
At present, clone the source and build it using
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,9 @@
|
||||||
<!DOCTYPE html PUBLIC ""
|
<!DOCTYPE html PUBLIC ""
|
||||||
"">
|
"">
|
||||||
<html><head><meta charset="UTF-8" /><title>beowulf.read documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.0</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 current"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="beowulf.read.html#var-gen-cond"><div class="inner"><span>gen-cond</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-gen-cond-clause"><div class="inner"><span>gen-cond-clause</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-gen-dot-terminated-list"><div class="inner"><span>gen-dot-terminated-list</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-gen-fn-call"><div class="inner"><span>gen-fn-call</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-generate"><div class="inner"><span>generate</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-gsp"><div class="inner"><span>gsp</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-parse"><div class="inner"><span>parse</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-READ"><div class="inner"><span>READ</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-simplify"><div class="inner"><span>simplify</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-strip-leading-zeros"><div class="inner"><span>strip-leading-zeros</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">beowulf.read</h1><div class="doc"><div class="markdown"><p>This provides the reader required for boostrapping. It’s not a bad reader - it provides feedback on errors found in the input - but it isn’t the real Lisp reader.</p>
|
<html><head><meta charset="UTF-8" /><title>beowulf.read documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch current"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="beowulf.read.html#var-gsp"><div class="inner"><span>gsp</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-number-lines"><div class="inner"><span>number-lines</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-READ"><div class="inner"><span>READ</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-read-from-console"><div class="inner"><span>read-from-console</span></div></a></li><li class="depth-1"><a href="beowulf.read.html#var-strip-line-comments"><div class="inner"><span>strip-line-comments</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">beowulf.read</h1><div class="doc"><div class="markdown"><p>This provides the reader required for boostrapping. It’s not a bad reader - it provides feedback on errors found in the input - but it isn’t the real Lisp reader.</p>
|
||||||
<p>Intended deviations from the behaviour of the real Lisp reader are as follows:</p>
|
<p>Intended deviations from the behaviour of the real Lisp reader are as follows:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>It reads the meta-expression language <code>MEXPR</code> in addition to the symbolic expression language <code>SEXPR</code>, which I do not believe the Lisp 1.5 reader ever did;</li>
|
<li>It reads the meta-expression language <code>MEXPR</code> in addition to fLAMthe symbolic expression language <code>SEXPR</code>, which I do not believe the Lisp 1.5 reader ever did;</li>
|
||||||
<li>It treats everything between a semi-colon and an end of line as a comment, as most modern Lisps do; but I do not believe Lisp 1.5 had this feature.</li>
|
<li>It treats everything between a semi-colon and an end of line as a comment, as most modern Lisps do; but I do not believe Lisp 1.5 had this feature.</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p>Both these extensions can be disabled by using the <code>--strict</code> command line switch.</p></div></div><div class="public anchor" id="var-gen-cond"><h3>gen-cond</h3><div class="usage"><code>(gen-cond p)</code></div><div class="doc"><div class="markdown"><p>Generate a cond statement from this simplified parse tree fragment <code>p</code>; returns <code>nil</code> if <code>p</code> does not represent a (MEXPR) cond statement.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L206">view source</a></div></div><div class="public anchor" id="var-gen-cond-clause"><h3>gen-cond-clause</h3><div class="usage"><code>(gen-cond-clause p)</code></div><div class="doc"><div class="markdown"><p>Generate a cond clause from this simplified parse tree fragment <code>p</code>; returns <code>nil</code> if <code>p</code> does not represent a cond clause.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L196">view source</a></div></div><div class="public anchor" id="var-gen-dot-terminated-list"><h3>gen-dot-terminated-list</h3><div class="usage"><code>(gen-dot-terminated-list p)</code></div><div class="doc"><div class="markdown"><p>Generate a list, which may be dot-terminated, from this partial parse tree ‘p’. Note that the function acts recursively and progressively decapitates its argument, so that the argument will not always be a valid parse tree.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L230">view source</a></div></div><div class="public anchor" id="var-gen-fn-call"><h3>gen-fn-call</h3><div class="usage"><code>(gen-fn-call p)</code></div><div class="doc"><div class="markdown"><p>Generate a function call from this simplified parse tree fragment <code>p</code>; returns <code>nil</code> if <code>p</code> does not represent a (MEXPR) function call.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L219">view source</a></div></div><div class="public anchor" id="var-generate"><h3>generate</h3><div class="usage"><code>(generate p)</code></div><div class="doc"><div class="markdown"><p>Generate lisp structure from this parse tree <code>p</code>. It is assumed that <code>p</code> has been simplified.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L263">view source</a></div></div><div class="public anchor" id="var-gsp"><h3>gsp</h3><h4 class="type">macro</h4><div class="usage"><code>(gsp s)</code></div><div class="doc"><div class="markdown"><p>Shortcut macro - the internals of read; or, if you like, read-string. Argument <code>s</code> should be a string representation of a valid Lisp expression.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L304">view source</a></div></div><div class="public anchor" id="var-parse"><h3>parse</h3><div class="usage"></div><div class="doc"><div class="markdown"><p>Parse a string presented as argument into a parse tree which can then be operated upon further.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L32">view source</a></div></div><div class="public anchor" id="var-READ"><h3>READ</h3><div class="usage"><code>(READ input)</code></div><div class="doc"><div class="markdown"><p>An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L311">view source</a></div></div><div class="public anchor" id="var-simplify"><h3>simplify</h3><div class="usage"><code>(simplify p)</code><code>(simplify p context)</code></div><div class="doc"><div class="markdown"><p>Simplify this parse tree <code>p</code>. If <code>p</code> is an instaparse failure object, throw an <code>ex-info</code>, with <code>p</code> as the value of its <code>:failure</code> key.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L90">view source</a></div></div><div class="public anchor" id="var-strip-leading-zeros"><h3>strip-leading-zeros</h3><div class="usage"><code>(strip-leading-zeros s)</code><code>(strip-leading-zeros s prefix)</code></div><div class="doc"><div class="markdown"><p><code>read-string</code> interprets strings with leading zeros as octal; strip any from this string <code>s</code>. If what’s left is empty (i.e. there were only zeros, return <code>"0"</code>.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L249">view source</a></div></div></div></body></html>
|
<p>Both these extensions can be disabled by using the <code>--strict</code> command line switch.</p></div></div><div class="public anchor" id="var-gsp"><h3>gsp</h3><div class="usage"><code>(gsp s)</code></div><div class="doc"><div class="markdown"><p>Shortcut macro - the internals of read; or, if you like, read-string. Argument <code>s</code> should be a string representation of a valid Lisp expression.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L54">view source</a></div></div><div class="public anchor" id="var-number-lines"><h3>number-lines</h3><div class="usage"><code>(number-lines s)</code><code>(number-lines s e)</code></div><div class="doc"><div class="markdown"><p><strong>TODO</strong>: write docs</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L41">view source</a></div></div><div class="public anchor" id="var-READ"><h3>READ</h3><div class="usage"><code>(READ)</code><code>(READ input)</code></div><div class="doc"><div class="markdown"><p>An implementation of a Lisp reader sufficient for bootstrapping; not necessarily the final Lisp reader. <code>input</code> should be either a string representation of a LISP expression, or else an input stream. A single form will be read.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L75">view source</a></div></div><div class="public anchor" id="var-read-from-console"><h3>read-from-console</h3><div class="usage"><code>(read-from-console)</code></div><div class="doc"><div class="markdown"><p>Attempt to read a complete lisp expression from the console.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L66">view source</a></div></div><div class="public anchor" id="var-strip-line-comments"><h3>strip-line-comments</h3><div class="usage"><code>(strip-line-comments s)</code></div><div class="doc"><div class="markdown"><p>Strip blank lines and comment lines from this string <code>s</code>, expected to be Lisp source.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/read.clj#L31">view source</a></div></div></div></body></html>
|
3
docs/codox/beowulf.reader.generate.html
Normal file
3
docs/codox/beowulf.reader.generate.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/beowulf.reader.macros.html
Normal file
3
docs/codox/beowulf.reader.macros.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html PUBLIC ""
|
||||||
|
"">
|
||||||
|
<html><head><meta charset="UTF-8" /><title>beowulf.reader.macros documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch current"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="beowulf.reader.macros.html#var-*readmacros*"><div class="inner"><span>*readmacros*</span></div></a></li><li class="depth-1"><a href="beowulf.reader.macros.html#var-expand-macros"><div class="inner"><span>expand-macros</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">beowulf.reader.macros</h1><div class="doc"><div class="markdown"><p>Can I implement reader macros? let’s see!</p></div></div><div class="public anchor" id="var-*readmacros*"><h3>*readmacros*</h3><h4 class="dynamic">dynamic</h4><div class="usage"></div><div class="doc"><div class="markdown"><p><strong>TODO</strong>: write docs</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/reader/macros.clj#L15">view source</a></div></div><div class="public anchor" id="var-expand-macros"><h3>expand-macros</h3><div class="usage"><code>(expand-macros form)</code></div><div class="doc"><div class="markdown"><p><strong>TODO</strong>: write docs</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/reader/macros.clj#L21">view source</a></div></div></div></body></html>
|
3
docs/codox/beowulf.reader.parser.html
Normal file
3
docs/codox/beowulf.reader.parser.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<!DOCTYPE html PUBLIC ""
|
||||||
|
"">
|
||||||
|
<html><head><meta charset="UTF-8" /><title>beowulf.reader.parser documentation</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 "><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch current"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="sidebar secondary"><h3><a href="#top"><span class="inner">Public Vars</span></a></h3><ul><li class="depth-1"><a href="beowulf.reader.parser.html#var-parse"><div class="inner"><span>parse</span></div></a></li></ul></div><div class="namespace-docs" id="content"><h1 class="anchor" id="top">beowulf.reader.parser</h1><div class="doc"><div class="markdown"><p>The actual parser, supporting both S-expression and M-expression syntax.</p></div></div><div class="public anchor" id="var-parse"><h3>parse</h3><div class="usage"></div><div class="doc"><div class="markdown"><p>Parse a string presented as argument into a parse tree which can then be operated upon further.</p></div></div><div class="src-link"><a href="https://github.com/simon-brooke/beowulf/blob/master/src/beowulf/reader/parser.clj#L5">view source</a></div></div></div></body></html>
|
3
docs/codox/beowulf.reader.simplify.html
Normal file
3
docs/codox/beowulf.reader.simplify.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html PUBLIC ""
|
<!DOCTYPE html PUBLIC ""
|
||||||
"">
|
"">
|
||||||
<html><head><meta charset="UTF-8" /><title>Introduction to beowulf</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.0</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#introduction-to-beowulf" name="introduction-to-beowulf"></a>Introduction to beowulf</h1>
|
<html><head><meta charset="UTF-8" /><title>Introduction to beowulf</title><link rel="stylesheet" type="text/css" href="css/default.css" /><link rel="stylesheet" type="text/css" href="css/highlight.css" /><script type="text/javascript" src="js/highlight.min.js"></script><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/page_effects.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body><div id="header"><h2>Generated by <a href="https://github.com/weavejester/codox">Codox</a></h2><h1><a href="index.html"><span class="project-title"><span class="project-name">Beowulf</span> <span class="project-version">0.2.1-SNAPSHOT</span></span></a></h1></div><div class="sidebar primary"><h3 class="no-link"><span class="inner">Project</span></h3><ul class="index-link"><li class="depth-1 "><a href="index.html"><div class="inner">Index</div></a></li></ul><h3 class="no-link"><span class="inner">Topics</span></h3><ul><li class="depth-1 current"><a href="intro.html"><div class="inner"><span>Introduction to beowulf</span></div></a></li></ul><h3 class="no-link"><span class="inner">Namespaces</span></h3><ul><li class="depth-1"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>beowulf</span></div></div></li><li class="depth-2 branch"><a href="beowulf.bootstrap.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>bootstrap</span></div></a></li><li class="depth-2 branch"><a href="beowulf.cons-cell.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>cons-cell</span></div></a></li><li class="depth-2 branch"><a href="beowulf.core.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>core</span></div></a></li><li class="depth-2 branch"><a href="beowulf.host.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>host</span></div></a></li><li class="depth-2 branch"><a href="beowulf.read.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>read</span></div></a></li><li class="depth-2"><div class="no-link"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>reader</span></div></div></li><li class="depth-3 branch"><a href="beowulf.reader.generate.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>generate</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.macros.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>macros</span></div></a></li><li class="depth-3 branch"><a href="beowulf.reader.parser.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>parser</span></div></a></li><li class="depth-3"><a href="beowulf.reader.simplify.html"><div class="inner"><span class="tree"><span class="top"></span><span class="bottom"></span></span><span>simplify</span></div></a></li></ul></div><div class="document" id="content"><div class="doc"><div class="markdown"><h1><a href="#introduction-to-beowulf" name="introduction-to-beowulf"></a>Introduction to beowulf</h1>
|
||||||
<p>TODO: write <a href="http://jacobian.org/writing/what-to-write/">great documentation</a></p></div></div></div></body></html>
|
<p>TODO: write <a href="http://jacobian.org/writing/what-to-write/">great documentation</a></p></div></div></div></body></html>
|
BIN
resources/img/screenshot.png
Normal file
BIN
resources/img/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
resources/img/screenshot.xcf
Normal file
BIN
resources/img/screenshot.xcf
Normal file
Binary file not shown.
|
@ -61,10 +61,10 @@
|
||||||
[x]
|
[x]
|
||||||
`(if (or (symbol? ~x) (number? ~x)) T NIL))
|
`(if (or (symbol? ~x) (number? ~x)) T NIL))
|
||||||
|
|
||||||
(defmacro CONS
|
(defn CONS
|
||||||
"Construct a new instance of cons cell with this `car` and `cdr`."
|
"Construct a new instance of cons cell with this `car` and `cdr`."
|
||||||
[car cdr]
|
[car cdr]
|
||||||
`(beowulf.cons_cell.ConsCell. ~car ~cdr))
|
(beowulf.cons_cell.ConsCell. car cdr (gensym "c")))
|
||||||
|
|
||||||
(defn CAR
|
(defn CAR
|
||||||
"Return the item indicated by the first pointer of a pair. NIL is treated
|
"Return the item indicated by the first pointer of a pair. NIL is treated
|
||||||
|
@ -406,12 +406,12 @@
|
||||||
"Implementation of SET in Clojure. Add to the `oblist` a binding of the
|
"Implementation of SET in Clojure. Add to the `oblist` a binding of the
|
||||||
value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
|
value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
|
||||||
[symbol val]
|
[symbol val]
|
||||||
(doall
|
(when
|
||||||
(swap!
|
(swap!
|
||||||
oblist
|
oblist
|
||||||
(fn [ob s v] (make-cons-cell (make-cons-cell s v) ob))
|
(fn [ob s v] (make-cons-cell (make-cons-cell s v) ob))
|
||||||
symbol val)
|
symbol val)
|
||||||
NIL))
|
NIL))
|
||||||
|
|
||||||
(defn APPLY
|
(defn APPLY
|
||||||
"For bootstrapping, at least, a version of APPLY written in Clojure.
|
"For bootstrapping, at least, a version of APPLY written in Clojure.
|
||||||
|
@ -437,14 +437,14 @@
|
||||||
(= function 'EQ) (apply EQ args)
|
(= function 'EQ) (apply EQ args)
|
||||||
(= function 'INTEROP) (INTEROP (CAR args) (CDR args))
|
(= function 'INTEROP) (INTEROP (CAR args) (CDR args))
|
||||||
(= function 'SET) (SET (CAR args) (CADR args))
|
(= function 'SET) (SET (CAR args) (CADR args))
|
||||||
(EVAL function environment)(APPLY
|
(EVAL function environment) (APPLY
|
||||||
(EVAL function environment)
|
(EVAL function environment)
|
||||||
args
|
args
|
||||||
environment)
|
environment)
|
||||||
:else
|
:else
|
||||||
(throw (ex-info "No function found" {:context "APPLY"
|
(throw (ex-info "No function found" {:context "APPLY"
|
||||||
:function function
|
:function function
|
||||||
:args args})))
|
:args args})))
|
||||||
(fn? function) ;; i.e., it's a Clojure function
|
(fn? function) ;; i.e., it's a Clojure function
|
||||||
(apply function (to-clojure args))
|
(apply function (to-clojure args))
|
||||||
(= (first function) 'LAMBDA) (EVAL
|
(= (first function) 'LAMBDA) (EVAL
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"provides Lisp 1.5 functions which can't be (or can't efficiently
|
"provides Lisp 1.5 functions which can't be (or can't efficiently
|
||||||
be) implemented in Lisp 1.5, which therefore need to be implemented in the
|
be) implemented in Lisp 1.5, which therefore need to be implemented in the
|
||||||
host language, in this case Clojure."
|
host language, in this case Clojure."
|
||||||
(:require [beowulf.cons-cell :refer [T NIL F]]
|
(:require [beowulf.cons-cell :refer [F make-beowulf-list NIL T]]
|
||||||
;; note hyphen - this is Clojure...
|
;; note hyphen - this is Clojure...
|
||||||
)
|
)
|
||||||
(:import [beowulf.cons_cell ConsCell]
|
(:import [beowulf.cons_cell ConsCell]
|
||||||
|
@ -13,7 +13,6 @@
|
||||||
;; those which can be implemented in Lisp should be, since that aids
|
;; those which can be implemented in Lisp should be, since that aids
|
||||||
;; portability.
|
;; portability.
|
||||||
|
|
||||||
|
|
||||||
(defn RPLACA
|
(defn RPLACA
|
||||||
"Replace the CAR pointer of this `cell` with this `value`. Dangerous, should
|
"Replace the CAR pointer of this `cell` with this `value`. Dangerous, should
|
||||||
really not exist, but does in Lisp 1.5 (and was important for some
|
really not exist, but does in Lisp 1.5 (and was important for some
|
||||||
|
@ -109,3 +108,7 @@
|
||||||
(defn NUMBERP
|
(defn NUMBERP
|
||||||
[x]
|
[x]
|
||||||
(if (number? x) T F))
|
(if (number? x) T F))
|
||||||
|
|
||||||
|
(defn LIST
|
||||||
|
[& args]
|
||||||
|
(make-beowulf-list args))
|
|
@ -15,7 +15,7 @@
|
||||||
switch."
|
switch."
|
||||||
(:require [beowulf.reader.generate :refer [generate]]
|
(:require [beowulf.reader.generate :refer [generate]]
|
||||||
[beowulf.reader.parser :refer [parse]]
|
[beowulf.reader.parser :refer [parse]]
|
||||||
[beowulf.reader.simplify :refer [simplify]]
|
[beowulf.reader.simplify :refer [remove-optional-space simplify]]
|
||||||
[clojure.string :refer [join split starts-with? trim]])
|
[clojure.string :refer [join split starts-with? trim]])
|
||||||
(:import [java.io InputStream]
|
(:import [java.io InputStream]
|
||||||
[instaparse.gll Failure]))
|
[instaparse.gll Failure]))
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
(if (instance? Failure parse-tree)
|
(if (instance? Failure parse-tree)
|
||||||
(doall (println (number-lines source parse-tree))
|
(doall (println (number-lines source parse-tree))
|
||||||
(throw (ex-info "Parse failed" (assoc parse-tree :source source))))
|
(throw (ex-info "Parse failed" (assoc parse-tree :source source))))
|
||||||
(generate (simplify parse-tree)))))
|
(generate (simplify (remove-optional-space parse-tree))))))
|
||||||
|
|
||||||
(defn read-from-console
|
(defn read-from-console
|
||||||
"Attempt to read a complete lisp expression from the console."
|
"Attempt to read a complete lisp expression from the console."
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns beowulf.reader.generate
|
(ns beowulf.reader.generate
|
||||||
(:require [beowulf.cons-cell :refer [make-beowulf-list make-cons-cell NIL]]
|
(:require [beowulf.cons-cell :refer [make-beowulf-list make-cons-cell NIL]]
|
||||||
|
[beowulf.reader.macros :refer [expand-macros]]
|
||||||
[clojure.math.numeric-tower :refer [expt]]
|
[clojure.math.numeric-tower :refer [expt]]
|
||||||
[clojure.string :refer [upper-case]]))
|
[clojure.string :refer [upper-case]]))
|
||||||
|
|
||||||
|
@ -119,6 +120,15 @@
|
||||||
(cons (generate (nth (second tree) 2))
|
(cons (generate (nth (second tree) 2))
|
||||||
(map generate (-> tree rest rest rest))))))))
|
(map generate (-> tree rest rest rest))))))))
|
||||||
|
|
||||||
|
(defn gen-iexpr
|
||||||
|
[tree]
|
||||||
|
(let [bundle (reduce #(assoc %1 (first %2) (nth %2 1))
|
||||||
|
{}
|
||||||
|
(rest tree))]
|
||||||
|
(list (generate (:iop bundle))
|
||||||
|
(generate (:lhs bundle))
|
||||||
|
(generate (:rhs bundle)))))
|
||||||
|
|
||||||
(defn generate-set
|
(defn generate-set
|
||||||
"Actually not sure what the mexpr representation of set looks like"
|
"Actually not sure what the mexpr representation of set looks like"
|
||||||
[tree]
|
[tree]
|
||||||
|
@ -152,46 +162,51 @@
|
||||||
`p` has been simplified."
|
`p` has been simplified."
|
||||||
[p]
|
[p]
|
||||||
(try
|
(try
|
||||||
(if
|
(expand-macros
|
||||||
(coll? p)
|
(if
|
||||||
(case (first p)
|
(coll? p)
|
||||||
:λ "LAMBDA"
|
(case (first p)
|
||||||
:λexpr (make-cons-cell
|
">" 'GREATERP
|
||||||
(generate (nth p 1))
|
:λ "LAMBDA"
|
||||||
(make-cons-cell (generate (nth p 2))
|
:λexpr (make-cons-cell
|
||||||
(generate (nth p 3))))
|
(generate (nth p 1))
|
||||||
:args (make-beowulf-list (map generate (rest p)))
|
(make-cons-cell (generate (nth p 2))
|
||||||
:atom (symbol (second p))
|
(generate (nth p 3))))
|
||||||
:bindings (generate (second p))
|
:args (make-beowulf-list (map generate (rest p)))
|
||||||
:body (make-beowulf-list (map generate (rest p)))
|
:atom (symbol (second p))
|
||||||
:cond (gen-cond p)
|
:bindings (generate (second p))
|
||||||
:cond-clause (gen-cond-clause p)
|
:body (make-beowulf-list (map generate (rest p)))
|
||||||
(:decimal :integer) (read-string (strip-leading-zeros (second p)))
|
:cond (gen-cond p)
|
||||||
:defn (generate-assign p)
|
:cond-clause (gen-cond-clause p)
|
||||||
:dotted-pair (make-cons-cell
|
(:decimal :integer) (read-string (strip-leading-zeros (second p)))
|
||||||
(generate (nth p 1))
|
:defn (generate-assign p)
|
||||||
(generate (nth p 2)))
|
:dotted-pair (make-cons-cell
|
||||||
:exponent (generate (second p))
|
(generate (nth p 1))
|
||||||
:fncall (gen-fn-call p)
|
(generate (nth p 2)))
|
||||||
:list (gen-dot-terminated-list (rest p))
|
:exponent (generate (second p))
|
||||||
:mvar (symbol (upper-case (second p)))
|
:fncall (gen-fn-call p)
|
||||||
:octal (let [n (read-string (strip-leading-zeros (second p) "0"))
|
:iexpr (gen-iexpr p)
|
||||||
scale (generate (nth p 2))]
|
:list (gen-dot-terminated-list (rest p))
|
||||||
(* n (expt 8 scale)))
|
(:lhs :rhs) (generate (second p))
|
||||||
|
:mexpr (generate (second p))
|
||||||
|
:mvar (symbol (upper-case (second p)))
|
||||||
|
:octal (let [n (read-string (strip-leading-zeros (second p) "0"))
|
||||||
|
scale (generate (nth p 2))]
|
||||||
|
(* n (expt 8 scale)))
|
||||||
|
|
||||||
;; the quote read macro (which probably didn't exist in Lisp 1.5, but...)
|
;; the quote read macro (which probably didn't exist in Lisp 1.5, but...)
|
||||||
:quoted-expr (make-beowulf-list (list 'QUOTE (generate (second p))))
|
:quoted-expr (make-beowulf-list (list 'QUOTE (generate (second p))))
|
||||||
:scale-factor (if
|
:scale-factor (if
|
||||||
(empty? (second p)) 0
|
(empty? (second p)) 0
|
||||||
(read-string (strip-leading-zeros (second p))))
|
(read-string (strip-leading-zeros (second p))))
|
||||||
:scientific (let [n (generate (second p))
|
:scientific (let [n (generate (second p))
|
||||||
exponent (generate (nth p 2))]
|
exponent (generate (nth p 2))]
|
||||||
(* n (expt 10 exponent)))
|
(* n (expt 10 exponent)))
|
||||||
|
|
||||||
;; default
|
;; default
|
||||||
(throw (ex-info (str "Unrecognised head: " (first p))
|
(throw (ex-info (str "Unrecognised head: " (first p))
|
||||||
{:generating p})))
|
{:generating p})))
|
||||||
p)
|
p))
|
||||||
(catch Throwable any
|
(catch Throwable any
|
||||||
(throw (ex-info "Could not generate"
|
(throw (ex-info "Could not generate"
|
||||||
{:generating p}
|
{:generating p}
|
||||||
|
|
36
src/beowulf/reader/macros.clj
Normal file
36
src/beowulf/reader/macros.clj
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
(ns beowulf.reader.macros
|
||||||
|
"Can I implement reader macros? let's see!"
|
||||||
|
(:require [beowulf.bootstrap :refer [CADR CADDR CDDR CONS]]
|
||||||
|
[beowulf.cons-cell :refer [make-beowulf-list]]
|
||||||
|
[beowulf.host :refer [LIST]]
|
||||||
|
[clojure.string :refer [join]])
|
||||||
|
(:import [beowulf.cons_cell ConsCell]))
|
||||||
|
|
||||||
|
;; We don't need (at least, in the Clojure reader) to rewrite forms like
|
||||||
|
;; "'FOO", because that's handled by the parser. But we do need to rewrite
|
||||||
|
;; things which don't evaluate their arguments, like `SETQ`, because (unless
|
||||||
|
;; LABEL does it, which I'm not yet sure of) we're not yet able to implement
|
||||||
|
;; things which don't evaluate arguments.
|
||||||
|
|
||||||
|
(def ^:dynamic *readmacros*
|
||||||
|
{:car {'DEFUN (fn [f]
|
||||||
|
(LIST 'SET (LIST 'QUOTE (CADR f))
|
||||||
|
(CONS 'LAMBDA (CDDR f))))
|
||||||
|
'SETQ (fn [f] (LIST 'SET (LIST 'QUOTE (CADR f)) (CADDR f)))}})
|
||||||
|
|
||||||
|
(defn expand-macros
|
||||||
|
[form]
|
||||||
|
(try
|
||||||
|
(if-let [car (when (and (coll? form) (symbol? (first form)))
|
||||||
|
(first form))]
|
||||||
|
(if-let [macro (-> *readmacros* :car car)]
|
||||||
|
(make-beowulf-list (apply macro (list form)))
|
||||||
|
form)
|
||||||
|
form)
|
||||||
|
(catch Exception any
|
||||||
|
(println (join "\n"
|
||||||
|
["# ERROR while expanding macro:"
|
||||||
|
(str "# Form: " form)
|
||||||
|
(str "# Error class: " (.getName (.getClass any)))
|
||||||
|
(str "# Message: " (.getMessage any))]))
|
||||||
|
form)))
|
|
@ -46,7 +46,7 @@
|
||||||
;; Infix operators appear in mexprs, e.g. on page 7. Ooops!
|
;; Infix operators appear in mexprs, e.g. on page 7. Ooops!
|
||||||
;; I do not know what infix operators are considered legal.
|
;; I do not know what infix operators are considered legal.
|
||||||
"iexpr := iexp iop iexp;
|
"iexpr := iexp iop iexp;
|
||||||
iexp := mexpr | mvar | number | mexpr | opt-space iexp opt-space;
|
iexp := mexpr | number | opt-space iexp opt-space;
|
||||||
iop := '>' | '<' | '+' | '-' | '/' | '=' ;"
|
iop := '>' | '<' | '+' | '-' | '/' | '=' ;"
|
||||||
|
|
||||||
;; comments. I'm pretty confident Lisp 1.5 did NOT have these.
|
;; comments. I'm pretty confident Lisp 1.5 did NOT have these.
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
"Simplify parse trees. Be aware that this is very tightly coupled
|
"Simplify parse trees. Be aware that this is very tightly coupled
|
||||||
with the parser."
|
with the parser."
|
||||||
(:require [beowulf.bootstrap :refer [*options*]]
|
(:require [beowulf.bootstrap :refer [*options*]]
|
||||||
|
[clojure.tools.trace :refer [deftrace]]
|
||||||
[instaparse.failure :as f])
|
[instaparse.failure :as f])
|
||||||
(:import [instaparse.gll Failure]))
|
(:import [instaparse.gll Failure]))
|
||||||
|
|
||||||
(declare simplify)
|
(declare simplify)
|
||||||
|
|
||||||
|
@ -12,83 +13,90 @@
|
||||||
(if (vector? tree)
|
(if (vector? tree)
|
||||||
(if (= :opt-space (first tree))
|
(if (= :opt-space (first tree))
|
||||||
nil
|
nil
|
||||||
(remove nil?
|
(let [v (remove nil?
|
||||||
(map remove-optional-space tree)))
|
(map remove-optional-space tree))]
|
||||||
|
(if (seq v)
|
||||||
|
(apply vector v)
|
||||||
|
v)))
|
||||||
tree))
|
tree))
|
||||||
|
|
||||||
(defn remove-nesting
|
(defn remove-nesting
|
||||||
[tree]
|
[tree context]
|
||||||
(let [tree' (remove-optional-space tree)]
|
(let [tree' (remove-optional-space tree)]
|
||||||
(if-let [key (when (and (vector? tree') (keyword? (first tree'))) (first tree'))]
|
(if-let [key (when (and (vector? tree')
|
||||||
|
(keyword? (first tree')))
|
||||||
|
(first tree'))]
|
||||||
(loop [r tree']
|
(loop [r tree']
|
||||||
(if (and r (vector? r) (keyword? (first r)))
|
(if (and r (vector? r) (keyword? (first r)))
|
||||||
(if (= (first r) key)
|
(if (= (first r) key)
|
||||||
(recur (simplify (second r) :foo))
|
(recur (simplify (second r) context))
|
||||||
r)
|
r)
|
||||||
r))
|
r))
|
||||||
tree')))
|
tree')))
|
||||||
|
|
||||||
|
|
||||||
(defn simplify
|
(defn simplify
|
||||||
"Simplify this parse tree `p`. If `p` is an instaparse failure object, throw
|
"Simplify this parse tree `p`. If `p` is an instaparse failure object, throw
|
||||||
an `ex-info`, with `p` as the value of its `:failure` key."
|
an `ex-info`, with `p` as the value of its `:failure` key."
|
||||||
([p]
|
([p]
|
||||||
(if
|
(if
|
||||||
(instance? Failure p)
|
(instance? Failure p)
|
||||||
(throw (ex-info (str "Ic ne behæfd: " (f/pprint-failure p)) {:cause :parse-failure
|
(throw (ex-info
|
||||||
:phase :simplify
|
(str "Ic ne behæfd: " (f/pprint-failure p))
|
||||||
:failure p}))
|
{:cause :parse-failure
|
||||||
|
:phase :simplify
|
||||||
|
:failure p}))
|
||||||
(simplify p :expr)))
|
(simplify p :expr)))
|
||||||
([p context]
|
([p context]
|
||||||
(if
|
(cond
|
||||||
(coll? p)
|
(string? p) p
|
||||||
(apply
|
(coll? p) (apply
|
||||||
vector
|
vector
|
||||||
(remove
|
(remove
|
||||||
#(when (coll? %) (empty? %))
|
#(when (coll? %) (empty? %))
|
||||||
(case (first p)
|
(case (first p)
|
||||||
(:λexpr
|
(:λexpr
|
||||||
:args :bindings :body :cond :cond-clause :defn :dot-terminal
|
:args :bindings :body :cond :cond-clause :defn :dot-terminal
|
||||||
:fncall :lhs :octal :quoted-expr :rhs :scientific) (map #(simplify % context) p)
|
:fncall :lhs :octal :quoted-expr :rhs :scientific) (map #(simplify % context) p)
|
||||||
(:arg :expr :coefficient :fn-name :number) (simplify (second p) context)
|
(:arg :expr :coefficient :fn-name :number) (simplify (second p) context)
|
||||||
(:arrow :dot :e :lpar :lsqb :opt-comment :opt-space :q :quote :rpar :rsqb
|
(:arrow :dot :e :lpar :lsqb :opt-comment :opt-space :q :quote :rpar :rsqb
|
||||||
:semi-colon :sep :space) nil
|
:semi-colon :sep :space) nil
|
||||||
:atom (if
|
:atom (if
|
||||||
(= context :mexpr)
|
(= context :mexpr)
|
||||||
[:quoted-expr p]
|
[:quoted-expr p]
|
||||||
p)
|
p)
|
||||||
:comment (when
|
:comment (when
|
||||||
(:strict *options*)
|
(:strict *options*)
|
||||||
(throw
|
(throw
|
||||||
(ex-info "Cannot parse comments in strict mode"
|
(ex-info "Cannot parse comments in strict mode"
|
||||||
{:cause :strict})))
|
{:cause :strict})))
|
||||||
:dotted-pair (if
|
:decimal p
|
||||||
(= context :mexpr)
|
:dotted-pair (if
|
||||||
[:fncall
|
(= context :mexpr)
|
||||||
[:mvar "cons"]
|
[:fncall
|
||||||
[:args
|
[:mvar "cons"]
|
||||||
(simplify (nth p 1) context)
|
[:args
|
||||||
(simplify (nth p 2) context)]]
|
(simplify (nth p 1) context)
|
||||||
(map simplify p))
|
(simplify (nth p 2) context)]]
|
||||||
:iexp (second (remove-nesting p))
|
(map #(simplify % context) p))
|
||||||
:iexpr [:iexpr
|
:iexp (simplify (second p) context)
|
||||||
[:lhs (simplify (second p) context)]
|
:iexpr [:iexpr
|
||||||
(simplify (nth p 2) context) ;; really should be the operator
|
[:lhs (simplify (second p) context)]
|
||||||
[:rhs (simplify (nth p 3) context)]]
|
(simplify (nth p 2) context) ;; really should be the operator
|
||||||
:mexpr (if
|
[:rhs (simplify (nth p 3) context)]]
|
||||||
(:strict *options*)
|
:mexpr (if
|
||||||
(throw
|
(:strict *options*)
|
||||||
(ex-info "Cannot parse meta expressions in strict mode"
|
(throw
|
||||||
{:cause :strict}))
|
(ex-info "Cannot parse meta expressions in strict mode"
|
||||||
(simplify (second p) :mexpr))
|
{:cause :strict}))
|
||||||
:list (if
|
(simplify (second p) :mexpr))
|
||||||
(= context :mexpr)
|
:list (if
|
||||||
[:fncall
|
(= context :mexpr)
|
||||||
[:mvar "list"]
|
[:fncall
|
||||||
[:args (apply vector (map simplify (rest p)))]]
|
[:mvar "list"]
|
||||||
(map #(simplify % context) p))
|
[:args (apply vector (map simplify (rest p)))]]
|
||||||
:raw (first (remove empty? (map simplify (rest p))))
|
(map #(simplify % context) p))
|
||||||
:sexpr (simplify (second p) :sexpr)
|
:raw (first (remove empty? (map simplify (rest p))))
|
||||||
|
:sexpr (simplify (second p) :sexpr)
|
||||||
;;default
|
;;default
|
||||||
p)))
|
p)))
|
||||||
p)))
|
:else p)))
|
||||||
|
|
11
test/beowulf/reader_macro_test.clj
Normal file
11
test/beowulf/reader_macro_test.clj
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
(ns beowulf.reader-macro-test
|
||||||
|
(:require [clojure.test :refer [deftest is testing]]
|
||||||
|
[beowulf.read :refer [gsp]]
|
||||||
|
[beowulf.reader.macros :refer [expand-macros]]))
|
||||||
|
|
||||||
|
(deftest macro-expansion
|
||||||
|
(testing "Expanding DEFUN"
|
||||||
|
(let [expected "(SET (QUOTE FACT) (LAMBDA (X) (COND ((ZEROP X) 1) (T (TIMES X (FACT (SUB1 X)))))))"
|
||||||
|
source "(DEFUN FACT (X) (COND ((ZEROP X) 1) (T (TIMES X (FACT (SUB1 X))))))"
|
||||||
|
actual (print-str (gsp source))]
|
||||||
|
(is (= actual expected)))))
|
|
@ -114,6 +114,6 @@
|
||||||
|
|
||||||
(deftest list-tests
|
(deftest list-tests
|
||||||
(testing "Reading arbitrarily structured lists"
|
(testing "Reading arbitrarily structured lists"
|
||||||
(let [expected "(DEFUN FACT (X) (COND ((ZEROP X) 1) (T (TIMES X (FACT (SUB1 X))))))"
|
(let [expected "(SET (QUOTE FACT) (LAMBDA (X) (COND ((ZEROP X) 1) (T (TIMES X (FACT (SUB1 X)))))))"
|
||||||
actual (print-str (gsp expected))]
|
actual (print-str (gsp expected))]
|
||||||
(is (= actual expected)))))
|
(is (= actual expected)))))
|
||||||
|
|
Loading…
Reference in a new issue