https://github.com/turbopape/scheje Skip to content Sign up * Product + Features + Mobile + Actions + Codespaces + Packages + Security + Code review + Issues + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Skills + GitHub Sponsors + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} turbopape / scheje Public * Notifications * Fork 10 * Star 125 A little scheme implementation on top of Clojure turbopape.github.io/scheje License MIT license 125 stars 10 forks Star Notifications * Code * Issues 6 * Pull requests 0 * Actions * Projects 0 * Wiki * Security * Insights More * Code * Issues * Pull requests * Actions * Projects * Wiki * Security * Insights turbopape/scheje This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. master Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 1 branch 18 tags Code Latest commit @contrepoint @turbopape contrepoint and turbopape remove extra spaces in interpreter tests (# 19) ... 8a7940d Oct 4, 2016 remove extra spaces in interpreter tests (#19) 8a7940d Git stats * 98 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time doc Changed to version 0.2.0: Using eval/apply, decent define-syntax Feb 1, 2016 src/scheje Fixed some typos May 29, 2016 test/scheje remove extra spaces in interpreter tests (#19) Oct 4, 2016 .gitignore Added vector-ref Mar 18, 2016 .travis.yml Removed openJDK8 from travis CI targets. Feb 7, 2016 CHANGELOG.md Lexical closures now work (#8) May 29, 2016 CODE_OF_CONDUCT.md Add Covenant CoC with gmail e-mail Sep 28, 2016 LICENSE Changed to version 0.2.0: Using eval/apply, decent define-syntax Feb 1, 2016 README.md Fixed a Typo in Readme Sep 28, 2016 Slack_Mark_Black_Web.png Added Slack Logo Mar 31, 2016 project.clj Bumped Cljs Version May 29, 2016 scheje-icon.png Adding icon (#18) Sep 28, 2016 scheje-logo.jpg New logo (#17) Sep 28, 2016 View code [ ] scheje - A little Scheme on Top of Clojure Usage Lexical Scoping in let Macros Hygienic Macros ClojureScript Support A little REPL Features Contributors TODOS - Wanna Contribute? Credits License README.md scheje - A little Scheme on Top of Clojure License MIT Build Status Clojars Project Gratipay Team Slack Team Scheje Logo "If you give someone Fortran, he has Fortran. If you give someone Lisp, he has any language he pleases." * Guy L. Steele Using the magnificent eval/apply dance (as in page 13 of the Lisp 1.5 Manual), scheje is a tiny scheme implementation on Top of Clojure. Scheje properly implements define-syntax, ellipsis is properly expanded into relevant symbols, which can be respectively used in the generated syntax-rules templates. In fact, even let is implemented in terms of define-syntax. The two defining forms, define and define-syntax generate new environments as per the bindings they introduce. Helper functions that interpret these along with other evaluations will be discussed later. Usage You can play with scheje on-line with the Web REPL. The main interpretation function is form-eval in the interpreter namespace. You give it a form and an environment, and you get your evaluation: (form-eval '(+ x y) '{x 1 y 2}) ;;=> 3 The function eval-prog, evaluates a whole program. This function is bootstrapped with a starting environment, called the library (see library.cljc for the contents of the library). When launched, eval-prog evaluates all the forms, only showing the value of the last one. Here are some examples: (eval-prog '((define-syntax let (syntax-rules () ((let ((var expr) ...) body ...) ((lambda (var ...) body ...) expr ...)))) (let ((x 1)(y 2)) (+ x y)))) ;;=>3 This example shows what we did to introduce the let form, though it is already implemented in the root environment used by scheje, so you don't have to define it every time you use eval-prog Analogous to let, here's how one can declare and using a recursive define-syntax: (eval-prog '((define-syntax and (syntax-rules () ((and x) x) ((and) true) ((and x y ...) (if x (and y ...) false)))) (and true true true true true false))) ;;=> false Same here, this is already defined in root-env so you don't have to define it every time you use eval-prog. or is defined in the same way: (eval-prog '((define-syntax or (syntax-rules () ((or x) x) ((or) true) ((or x y ...) (if x true (or y ...))))) (or false false false true false))) ;;=> true Last but not least, here is the must-have append function, necessary for every decent scheme implementation! (eval-prog '((define append (lambda (l1 l2) (cond ((null? l1) l2) (else (cons (car l1) (append (cdr l1) l2)))))) (append '(1 2 3) '(4 5 6)))) ;;=> '(1 2 3 4 5 6) Also, quote, quasiquote, unquote and unquote-splicing are supported: (form-eval '(quasiquote (1 (+ 1 (unquote-splicing (cdr '(1 2 3)))) (unquote (+ 1 a)))) { 'a 5}) ;;=> (1 (+ 1 2 3) 6) Also, named let, let*, and many more are available. Please refer to the test files for the interpreter namespace to see possible uses. Lexical Scoping in let Macros To prevent symbol capture when using the let macro, when expanded, each let introduced expression's symbols are stored in its own scope. This avoids name clash: In the following example, a is defined at the root-env, but "inner" a is returned from the let macro: (eval-prog '((define a "outer") (let ((x (and false false)) (a "inner")) (if x "_" a)))) ;;=> "inner" If we access a symbol outside the macro, we get its root binding: (eval-prog '((define a "outer") (let ((x (and false false)) (a "inner")) (if x "_" a)) a)) ;;=> "outer" Hygienic Macros Inspired by KFFD Algorithm. Now Scheje appends a timestamp with respect to the iteration in which every form is being expanded, thus preventing it from inadvertently capturing symbols across different expansion stages. If some symbols have timestamps that cannot be evaluated, Scheje tries to evaluate their "root" form, i.e, checks if their name, stripped out of the timestamps, isn't bound in the execution environment. This 'sort of' forces capture of such symbols, as to see if they were intended to be passed as globals, for instance. For instance, these two examples work properly: (eval-prog '( (define-syntax or2 (syntax-rules () ((or2 e1 e2) (let ((t e1)) (if t t e2) )))) (let ((t true)) (or2 false t )))) ;;=> true and (eval-prog '( (let ((if (lambda(x y z) "oops"))) (let ((g false)) (if g g false))))) ;;=> false ClojureScript Support Scheje is written using reader conditionals. The interpreter namespace can be used in a clojurescript project right away, in the browser, or in node.js if you want to use the file loading facilities. A little REPL Now a REPL namespace is shipped, exposing a little REPL permitting to evaluating expressions and loading files. If you want to run it in Clojure/JVM, just clone the repo and launch lein run You can also build a ClojureScript/Node.js REPL and enjoy the ultra fast startup compared to JVM's version. Simply proceed like so: #install npm dependencies npm install readline-sync # then build the node app lein cljsbuild once # and enjoy scheje.js :) node target/repl_out/scheje_repl.js Features Please refer to the Changelog and the interpreter_test.clj test file to get a comprehensive list of the features and usage of scheje. Contributors Thanks to these wonderful people who helped the development of Scheje: * balajirrao And to these awesome proof-readers: * jaredestroud * yurimalheiros * chasingSublimity * rom1504 Special thanks for the awesome logo go to: * morachimo TODOS - Wanna Contribute? You can see how you can help by seeing the open issues Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. Credits Scheje's Node.js REPL uses readLineSync from @anseki, which is licensed under the MIT License. License Copyright (c) 2016 Rafik Naccache and Contributors. Distributed under the terms of the MIT License. About A little scheme implementation on top of Clojure turbopape.github.io/scheje Topics programming-language scheme clojure lisp compiler macros evaluator Resources Readme License MIT license Code of conduct Code of conduct Stars 125 stars Watchers 6 watching Forks 10 forks Releases 18 tags Packages 0 No packages published Contributors 8 * @turbopape * @archcloudlabs * @morachimo * @yurimalheiros * @balajirrao * @rom1504 * @janiceshiu * @chasingSublimity Languages * Clojure 100.0% * (c) 2022 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.