├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── workflows │ └── ci.yaml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── sibilant ├── cli-help ├── docs ├── docs.json └── docs.txt ├── include ├── angular.sibilant ├── functional.sibilant └── node.sibilant ├── lib ├── browser.js ├── cli.js ├── options.js ├── repl.js └── sibilant.js ├── maps ├── browser.map ├── cli.map ├── options.map ├── repl.map └── sibilant.map ├── package.json ├── package.son ├── public ├── github-150.png ├── index.html ├── javascripts │ ├── browser.js │ ├── browser.map │ ├── jquery-2.1.4.js │ ├── jquery-2.1.4.min.js │ ├── jquery-2.1.4.min.map │ ├── jquery-ui.js │ ├── jquery.js │ ├── jquery.map │ ├── jquery.scrollNav.min.js │ ├── macros.sibilant │ ├── sibilant.info.js │ ├── sibilant.info.map │ └── sibilant.info.sibilant ├── maps │ └── browser.map ├── screen.css └── screen.scss ├── sibilant.js ├── sibilant.map ├── src ├── browser.sibilant ├── cli.sibilant ├── colors.sibilant ├── docs.sibilant ├── helpers.sibilant ├── macros.sibilant ├── macros │ ├── case.sibilant │ ├── comparison.sibilant │ ├── flow-control.sibilant │ ├── hash.sibilant │ ├── lambda.sibilant │ ├── lists.sibilant │ ├── loops.sibilant │ ├── macros.sibilant │ ├── math.sibilant │ ├── misc.sibilant │ ├── pipe.sibilant │ ├── predicates.sibilant │ ├── regex.sibilant │ ├── switch.sibilant │ └── variables.sibilant ├── node.sibilant ├── options.sibilant ├── output-formatter.sibilant ├── parser.sibilant ├── precompiled-macros.sibilant ├── pretty-printer.sibilant ├── repl.sibilant ├── require-and-include.sibilant ├── restructurer.sibilant ├── sibilant.sibilant ├── sourcemap.sibilant └── transpiler.sibilant ├── stool.sibilant ├── test ├── includeFile1.sibilant ├── includeFile2.sibilant ├── node.sibilant ├── require.son ├── slice.sibilant ├── test-angular.sibilant ├── test.sibilant ├── testHelper.sibilant └── var.sibilant └── version /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, religion, or sexual identity 11 | and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the 27 | overall community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or 32 | advances of any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email 36 | address, without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series 87 | of actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or 94 | permanent ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within 114 | the community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.0, available at 120 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 121 | 122 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 123 | enforcement ladder](https://github.com/mozilla/diversity). 124 | 125 | [homepage]: https://www.contributor-covenant.org 126 | 127 | For answers to common questions about this code of conduct, see the FAQ at 128 | https://www.contributor-covenant.org/faq. Translations are available at 129 | https://www.contributor-covenant.org/translations. 130 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | Contributions include code, documentation, answering user questions, running the 3 | project's infrastructure, and advocating for all types of users. 4 | 5 | The project welcomes all contributions from anyone willing to work in good faith 6 | with other contributors and the community. No contribution is too small and all 7 | contributions are valued. 8 | 9 | This guide explains the process for contributing to the project's GitHub 10 | Repository. 11 | 12 | - [Code of Conduct](#code-of-conduct) 13 | - [Bad Actors](#bad-actors) 14 | 15 | ## Code of Conduct 16 | The project has a [Code of Conduct](./CODE_OF_CONDUCT.md) that *all* 17 | contributors are expected to follow. This code describes the *minimum* behavior 18 | expectations for all contributors. 19 | 20 | As a contributor, how you choose to act and interact towards your 21 | fellow contributors, as well as to the community, will reflect back not only 22 | on yourself but on the project as a whole. The Code of Conduct is designed and 23 | intended, above all else, to help establish a culture within the project that 24 | allows anyone and everyone who wants to contribute to feel safe doing so. 25 | 26 | Should any individual act in any way that is considered in violation of the 27 | [Code of Conduct](./CODE_OF_CONDUCT.md), corrective actions will be taken. It is 28 | possible, however, for any individual to *act* in such a manner that is not in 29 | violation of the strict letter of the Code of Conduct guidelines while still 30 | going completely against the spirit of what that Code is intended to accomplish. 31 | 32 | Open, diverse, and inclusive communities live and die on the basis of trust. 33 | Contributors can disagree with one another so long as they trust that those 34 | disagreements are in good faith and everyone is working towards a common 35 | goal. 36 | 37 | ## Bad Actors 38 | All contributors to tacitly agree to abide by both the letter and 39 | spirit of the [Code of Conduct](./CODE_OF_CONDUCT.md). Failure, or 40 | unwillingness, to do so will result in contributions being respectfully 41 | declined. 42 | 43 | A *bad actor* is someone who repeatedly violates the *spirit* of the Code of 44 | Conduct through consistent failure to self-regulate the way in which they 45 | interact with other contributors in the project. In doing so, bad actors 46 | alienate other contributors, discourage collaboration, and generally reflect 47 | poorly on the project as a whole. 48 | 49 | Being a bad actor may be intentional or unintentional. Typically, unintentional 50 | bad behavior can be easily corrected by being quick to apologize and correct 51 | course *even if you are not entirely convinced you need to*. Giving other 52 | contributors the benefit of the doubt and having a sincere willingness to admit 53 | that you *might* be wrong is critical for any successful open collaboration. 54 | 55 | Don't be a bad actor. 56 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | build_and_test: 11 | name: Build and test 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | node-version: [8.x, 10.x, 12.x, 14.x] 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v1 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm install 23 | - run: npm run build --if-present 24 | - run: npm test 25 | env: 26 | CI: true 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | public/.sass-cache 3 | tmp/* 4 | *.swp 5 | node_modules 6 | .sass-cache 7 | .#* 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "6" 5 | - "5" 6 | - "4" 7 | 8 | notifications: 9 | webhooks: 10 | urls: 11 | - https://webhooks.gitter.im/e/a069578bce6f42dd26b3 12 | on_success: change # options: [always|never|change] default: always 13 | on_failure: always # options: [always|never|change] default: always 14 | on_start: never # options: [always|never|change] default: always 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Jacob Rothstein 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![CI](https://github.com/jbr/sibilant/workflows/CI/badge.svg) 2 | [![Gitter](https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg)](https://gitter.im/jbr/sibilant?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 3 | 4 | # Sibilant 5 | 6 | - Sibilant is a language that is parsed by javascript and compiles to 7 | javascript. 8 | - Sibilant is inspired by lisp and follows many lisp conventions, 9 | although it is still relatively close to the underlying javascript. 10 | - Macros can be defined in sibilant and included at compile time. 11 | - Sibilant is entirely written in sibilant. 12 | 13 | ## Language Priorities 14 | 15 | - Prefer verbose names to abbreviations by default. 16 | - Avoid line noise. Prefer established punctuation semantics from 17 | natural languages and common programming languages (eg commas come 18 | after things and mean a pause or separation). 19 | - Prefer readable and idiomatic javascript output, which necessitates 20 | sticking fairly closely to javascript semantics. Switching cost from 21 | sibilant to directly editing the output javascript should be low. 22 | - Prefer expressions to statements. This is the most notable exception 23 | to the adherance to idiomatic javascript. Self-executing functions 24 | are used extensively to this end. 25 | - Allow as much of the language to be modified in-source as 26 | possible. This includes the ability to rename/remove/redefine all 27 | keywords and macros. 28 | - Any language constructs that do not output readable javascript 29 | should be opt-in. 30 | - Add language features slowly, and only when there's a real use 31 | case. Don't blindly implement Lisp features without reasoning 32 | through the need. 33 | - Provide tools to simplify avoidance of repetition. 34 | 35 | ## Installation 36 | 37 | First, install [node.js](http://nodejs.org) [ 38 | [github](http://github.com/ry/node) ] and [npm](http://npmjs.org) [ 39 | [github](http://github.com/isaacs/npm) ]. Then, it's as simple as: 40 | 41 | $ npm install sibilant -g 42 | $ sibilant --help 43 | 44 | ## Hello world in the REPL 45 | 46 | $ sibilant 47 | sibilant> (+ 1 2) 48 | (1 + 2) 49 | result: 3 50 | sibilant> (console.log "hello world") 51 | console.log("hello world") 52 | hello world 53 | 54 | ## Try it before you install 55 | 56 | [sibilant.org](http://sibilant.org) includes an in-browser 57 | as-you-type sibilant compiler and tutorial, so you can get a sense of 58 | the language without leaving your browser. 59 | 60 | ## Learning the language 61 | 62 | The most up to date documentation is at 63 | [sibilant.org](https://sibilant.org) and [docs.sibilant.org](https://docs.sibilant.org). 64 | Also, check out [sibilant itself, 65 | which is written 100% in 66 | sibilant](http://github.com/jbr/sibilant/tree/main/src) to get a 67 | sense of what's possible. 68 | 69 | ## License 70 | 71 | Sibilant is released under the [MIT 72 | license](http://github.com/jbr/sibilant/blob/main/LICENSE) 73 | ([wikipedia](http://en.wikipedia.org/wiki/MIT_License)). 74 | -------------------------------------------------------------------------------- /bin/sibilant: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('./../lib/cli') 4 | -------------------------------------------------------------------------------- /cli-help: -------------------------------------------------------------------------------- 1 | Hi there! Thanks for installing sibilant. 2 | Please leave feedback on github issues (http://github.com/jbr/sibilant/issues) 3 | 4 | The current commandline options are 5 | -------------------------------------------------------------------------------- 6 | 7 | -v / --version Print out a version string and exit 8 | 9 | -h / --help This message 10 | 11 | --repl / [no args] Sibilant interactive command prompt 12 | 13 | --eval [optional STRING] / -e [optional STRING] 14 | Evaluate STRING if provided, otherwise evaluate STDIN. 15 | This is the same as -x -i [optional STRING] 16 | 17 | --execute / -x This is a flag. Execute input files in order supplied. 18 | 19 | --output DIR / -o DIR Output input files to this dir, replacing 20 | .sibilant with .js. 21 | 22 | --sourcemap [optional DIR] / -m [optional DIR] 23 | Use in conjunction with -o to build sourcemap files. If 24 | DIR is provided, .map files will be output there. If DIR 25 | is omitted, .map files will be output to the --output/-o 26 | DIR 27 | 28 | --input [optional STRING / -i [optional STRING] 29 | Interpret optional string as sibilant code. If the execute 30 | flag is set, execute this code. If STRING is not provided, 31 | read STDIN. 32 | 33 | --file FILE / -f FILE / FILE 34 | Add this file to the input files. If the execute flag is 35 | set, input files will be executed. If an output dir is 36 | specified, each file will be written to that dir. 37 | Otherwise, each file will be written to STDOUT. 38 | 39 | 40 | To pass arguments to an executed file, append them after a \"--\", as follows 41 | $ sibilant -x myfile.sibilant -- --arg-for-my-program=stuff 42 | 43 | myfile.sibilant will see process.argv as 44 | [ 'sibilant', 'myfile.sibilant', '--arg-for-my-program=stuff' ] 45 | 46 | -------------------------------------------------------------------------------- 47 | 48 | Examples 49 | 50 | to compile sibilant 51 | $ git clone git://github.com/jbr/sibilant.git 52 | $ npm link . 53 | $ sibilant src/*.sibilant -o lib 54 | $ sibilant -x test/test.sibilant # you're now running a sibilant you just compiled. 55 | 56 | to compile one file to stdout 57 | $ sibilant test/test.sibilant 58 | 59 | to compile a file to a directory 60 | $ sibilant test/test.sibilant -m -o . # put test.js and test.map here 61 | or 62 | $ sibilant --file test/test.sibilant --sourcemap --output . 63 | 64 | to run a file 65 | $ sibilant -x test/test.sibilant 66 | 67 | to enter the repl 68 | $ sibilant 69 | or 70 | $ sibilant --repl 71 | 72 | to see how something will translate to js, 73 | $ sibilant -i "(console.log (+ 2 2))" 74 | console.log((2 + 2)); 75 | 76 | to execute a quick snippet, 77 | $ sibilant -e "(console.log (+ 2 2))" # this is the same as -x -i 78 | 4 79 | 80 | to translate STDIN, 81 | $ echo "(console.log 'hello 'world)" | sibilant -i 82 | console.log("hello", "world"); 83 | 84 | to execute sibilant code on STDIN, 85 | $ echo "(console.log 'hello 'world)" | sibilant -e # or sibilant -x -i 86 | hello world 87 | -------------------------------------------------------------------------------- /include/angular.sibilant: -------------------------------------------------------------------------------- 1 | (macro ang-def (name args ...body) 2 | (macros.var name 3 | (apply macros.list (append 4 | (map args macros.quote) 5 | (apply macros.lambda 6 | (cons args body)))))) 7 | -------------------------------------------------------------------------------- /include/functional.sibilant: -------------------------------------------------------------------------------- 1 | (def bulk-map (arr fn) 2 | (var index 0 3 | group-size fn.length 4 | ret-arr []) 5 | 6 | (while (< index arr.length) 7 | (.push ret-arr 8 | (apply fn (send arr slice 9 | index (+ index group-size)))) 10 | (incr-by index group-size)) 11 | ret-arr) 12 | 13 | (def inject (start items fn) 14 | (if (list? items) 15 | (items.reduce fn start) 16 | start)) 17 | 18 | (def map (items fn) 19 | (if (list? items) 20 | (items.map fn) 21 | [])) 22 | 23 | (def select (items fn) 24 | (if (list? items) 25 | (items.filter fn) 26 | [])) 27 | 28 | (def detect (items fn) 29 | (when (list? items) 30 | (items.find fn))) 31 | 32 | (def all? (items fn) 33 | (when (list? items) 34 | (items.every fn))) 35 | 36 | (def none? (items fn) 37 | (when (list? items) 38 | (not (items.some fn)))) 39 | 40 | (def any? (items fn) 41 | (when (list? items) 42 | (items.some fn))) 43 | 44 | (def reject (items fn) 45 | (select items (#> (not (apply fn arguments))))) 46 | 47 | 48 | (def compact (arr) 49 | (select arr (#(item) 50 | (and 51 | (!= null item) 52 | (!= false item) 53 | (defined? item))))) 54 | 55 | (def unique (arr) 56 | (inject [] arr 57 | (#(coll item) 58 | (if (includes? coll item) 59 | coll 60 | (coll.concat [item]))))) 61 | 62 | 63 | (def interleave (glue arr) 64 | (when (and (string? arr) (list? glue)) 65 | (var temp glue) 66 | (assign glue arr 67 | arr temp)) 68 | 69 | (if (list? glue) (inject [] arr 70 | (#(collector item index) 71 | (collector.concat [item (get glue index)]))) 72 | 73 | 74 | (inject [(first arr)] (rest arr) 75 | (#(collector item index) (collector.concat [glue item]))))) 76 | 77 | 78 | (def flatten (items predicate) 79 | (if (list? items) 80 | (inject [] items 81 | (#(collector item) 82 | (if (or (not predicate) (predicate item)) 83 | [ ...collector 84 | ...(if (list? item) (flatten item predicate) item) ] 85 | collector))) 86 | 87 | (or (not predicate) (predicate items)) [items] 88 | 89 | [])) 90 | 91 | (def flat-compact (items) 92 | (flatten items (#(item) 93 | (and 94 | (!= null item) 95 | (!= false item) 96 | (defined? item))))) 97 | 98 | (def recurse-map (item fn) 99 | (if (list? item) (map item (#(subitem) (recurse-map subitem fn))) 100 | (fn item))) 101 | 102 | (def pluck (items attribute) 103 | (map items (#(item) (get item attribute)))) 104 | 105 | (def merge-into (into from) 106 | (Object.assign into from)) 107 | 108 | (def clone (object) 109 | (Object.assign {} object)) 110 | 111 | (def values (object) 112 | (|> object keys (map (#> (get object #0))))) 113 | 114 | (def map-values (object fn) 115 | (inject {} (keys object) 116 | (#(collector key index) 117 | (set collector key (fn (get object key) key)) 118 | collector))) 119 | 120 | (def merge-with (into from) 121 | (Object.assign {} into from)) 122 | -------------------------------------------------------------------------------- /include/node.sibilant: -------------------------------------------------------------------------------- 1 | (macro on (thing event ...args-and-body) 2 | (macros.send thing 'on (macros.quote event) (apply macros.lambda args-and-body))) 3 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (!(process.env.DISABLE_SOURCE_MAPS)) { 3 | return require("source-map-support").install(); 4 | } 5 | }).call(this); 6 | //# sourceMappingURL=../maps/cli.map 7 | ; 8 | var path = require("path"), 9 | fs = require("fs"), 10 | sibilant = require("../lib/sibilant.js"), 11 | options = require("../lib/options.js"), 12 | mod = require("module"); 13 | var runInSandbox = (function runInSandbox$(js, inputPath) { 14 | /* run-in-sandbox src/cli.sibilant:10:0 */ 15 | 16 | inputPath = (typeof inputPath !== "undefined") ? inputPath : "."; 17 | require.main.moduleCache = { }; 18 | require.main.filename = fs.realpathSync(inputPath); 19 | require.main.paths = mod._nodeModulePaths(path.dirname(fs.realpathSync(inputPath))); 20 | return require.main._compile(js, require.main.filename); 21 | }); 22 | var cli = { 23 | v: "version", 24 | h: "help", 25 | unhandled: "help", 26 | d: "docs", 27 | f: "file", 28 | o: "output", 29 | x: "execute", 30 | e: "eval", 31 | i: "input", 32 | m: "sourcemap", 33 | afterBreak: false, 34 | execute: false, 35 | unlabeled: "file" 36 | }; 37 | cli.version = (function cli$version$() { 38 | /* cli.version src/cli.sibilant:33:0 */ 39 | 40 | return console.log(sibilant.versionString()); 41 | }); 42 | cli.repl = (function cli$repl$(args) { 43 | /* cli.repl src/cli.sibilant:36:0 */ 44 | 45 | return require("../lib/repl"); 46 | }); 47 | var readStdin = (function readStdin$(fn) { 48 | /* read-stdin src/cli.sibilant:39:0 */ 49 | 50 | var stdin = process.stdin, 51 | data = ""; 52 | stdin.resume(); 53 | stdin.setEncoding("utf8"); 54 | stdin.on("data", (function(chunk) { 55 | /* src/cli.sibilant:44:21 */ 56 | 57 | return data = (data + chunk); 58 | })); 59 | return stdin.on("end", (function() { 60 | /* src/cli.sibilant:45:20 */ 61 | 62 | return fn(data); 63 | })); 64 | }); 65 | cli.eval = (function cli$eval$(args, options) { 66 | /* cli.eval src/cli.sibilant:47:0 */ 67 | 68 | options.execute = true; 69 | return cli.input(args, options); 70 | }); 71 | cli.input = (function cli$input$(args, options) { 72 | /* cli.input src/cli.sibilant:51:0 */ 73 | 74 | var process = (function process$(sibilantCode) { 75 | /* process src/cli.sibilant:52:5 */ 76 | 77 | var js = (sibilant(sibilantCode)).js; 78 | return (function() { 79 | if (options.execute) { 80 | return runInSandbox(js); 81 | } else { 82 | return console.log(js); 83 | } 84 | }).call(this); 85 | }); 86 | return (function() { 87 | if (0 === args.length) { 88 | return readStdin(process); 89 | } else { 90 | return process(args[0]); 91 | } 92 | }).call(this); 93 | }); 94 | cli.help = (function cli$help$(args, options) { 95 | /* cli.help src/cli.sibilant:61:0 */ 96 | 97 | return fs.readFile((__dirname + "/../cli-help"), { encoding: "utf8" }, (function(err, data) { 98 | /* src/cli.sibilant:63:19 */ 99 | 100 | (function() { 101 | if (err) { 102 | throw err 103 | } 104 | }).call(this); 105 | return console.log(data); 106 | })); 107 | }); 108 | var cliOptions = options(cli), 109 | args = (cliOptions.afterBreak || []); 110 | args.unshift(process.argv[1], "FILENAME"); 111 | process.argv = args; 112 | process.ARGV = args; 113 | (function() { 114 | if (0 === Object.keys(cliOptions).length) { 115 | return cli.repl(); 116 | } 117 | }).call(this); 118 | (function() { 119 | if (((typeof cliOptions.file === "undefined" || 0 === cliOptions.file.length) && cliOptions.docs)) { 120 | sibilant.include("./src/macros.sibilant"); 121 | return console.log(sibilant.docs[sibilant(cliOptions.docs[0]).js]()); 122 | } 123 | }).call(this); 124 | (cliOptions.file || []).forEach((function(inputFile) { 125 | /* src/cli.sibilant:87:0 */ 126 | 127 | var inputPath = (function() { 128 | if (inputFile.match((new RegExp("^\\/", undefined)))) { 129 | return inputFile; 130 | } else { 131 | return path.join(process.cwd(), inputFile); 132 | } 133 | }).call(this), 134 | inputExtname = path.extname(inputPath), 135 | inputBasename = path.basename(inputPath, inputExtname), 136 | json__QUERY = ".son" === inputExtname, 137 | map__QUERY = !(!(cliOptions.sourcemap)), 138 | result = sibilant({ 139 | file: inputPath, 140 | json: json__QUERY, 141 | map: map__QUERY 142 | }), 143 | outputDir = (function() { 144 | if (cliOptions.output) { 145 | return (cliOptions.output[0] || path.dirname(inputPath)); 146 | } 147 | }).call(this), 148 | mapDir = (function() { 149 | if (cliOptions.sourcemap) { 150 | return (cliOptions.sourcemap[0] || outputDir); 151 | } 152 | }).call(this), 153 | outputExtname = (function() { 154 | if (json__QUERY) { 155 | return ".json"; 156 | } else { 157 | return ".js"; 158 | } 159 | }).call(this); 160 | (function() { 161 | if (outputDir) { 162 | var outputPath = (path.join(outputDir, inputBasename) + outputExtname); 163 | fs.writeFileSync(outputPath, result.js); 164 | return (function() { 165 | if (mapDir) { 166 | var mapPath = (path.join(mapDir, inputBasename) + ".map"); 167 | return fs.writeFileSync(mapPath, result.map.toString()); 168 | } 169 | }).call(this); 170 | } else if (cliOptions.execute) { 171 | return runInSandbox(result.js, inputPath); 172 | } else { 173 | return console.log(result.js); 174 | } 175 | }).call(this); 176 | return (function() { 177 | if (cliOptions.docs) { 178 | return console.log(sibilant.docs[cliOptions.docs[0]]()); 179 | } 180 | }).call(this); 181 | })); -------------------------------------------------------------------------------- /lib/options.js: -------------------------------------------------------------------------------- 1 | var bulkMap = (function bulkMap$(arr, fn) { 2 | /* bulk-map include/functional.sibilant:1:0 */ 3 | 4 | var index = 0, 5 | groupSize = fn.length, 6 | retArr = []; 7 | (function() { 8 | var while$4 = undefined; 9 | while (index < arr.length) { 10 | while$4 = (function() { 11 | retArr.push(fn.apply(this, arr.slice(index, (index + groupSize)))); 12 | return index += groupSize; 13 | }).call(this); 14 | }; 15 | return while$4; 16 | }).call(this); 17 | return retArr; 18 | }); 19 | var inject = (function inject$(start, items, fn) { 20 | /* inject include/functional.sibilant:13:0 */ 21 | 22 | return (function() { 23 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 24 | return items.reduce(fn, start); 25 | } else { 26 | return start; 27 | } 28 | }).call(this); 29 | }); 30 | var map = (function map$(items, fn) { 31 | /* map include/functional.sibilant:18:0 */ 32 | 33 | return (function() { 34 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 35 | return items.map(fn); 36 | } else { 37 | return []; 38 | } 39 | }).call(this); 40 | }); 41 | var select = (function select$(items, fn) { 42 | /* select include/functional.sibilant:23:0 */ 43 | 44 | return (function() { 45 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 46 | return items.filter(fn); 47 | } else { 48 | return []; 49 | } 50 | }).call(this); 51 | }); 52 | var detect = (function detect$(items, fn) { 53 | /* detect include/functional.sibilant:28:0 */ 54 | 55 | return (function() { 56 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 57 | return items.find(fn); 58 | } 59 | }).call(this); 60 | }); 61 | var all__QUERY = (function all__QUERY$(items, fn) { 62 | /* all? include/functional.sibilant:32:0 */ 63 | 64 | return (function() { 65 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 66 | return items.every(fn); 67 | } 68 | }).call(this); 69 | }); 70 | var none__QUERY = (function none__QUERY$(items, fn) { 71 | /* none? include/functional.sibilant:36:0 */ 72 | 73 | return (function() { 74 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 75 | return !(items.some(fn)); 76 | } 77 | }).call(this); 78 | }); 79 | var any__QUERY = (function any__QUERY$(items, fn) { 80 | /* any? include/functional.sibilant:40:0 */ 81 | 82 | return (function() { 83 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 84 | return items.some(fn); 85 | } 86 | }).call(this); 87 | }); 88 | var reject = (function reject$(items, fn) { 89 | /* reject include/functional.sibilant:44:0 */ 90 | 91 | return select(items, (function() { 92 | /* include/functional.sibilant:45:16 */ 93 | 94 | return !(fn.apply(this, arguments)); 95 | })); 96 | }); 97 | var compact = (function compact$(arr) { 98 | /* compact include/functional.sibilant:48:0 */ 99 | 100 | return select(arr, (function(item) { 101 | /* include/functional.sibilant:49:17 */ 102 | 103 | return (null !== item && false !== item && typeof item !== "undefined"); 104 | })); 105 | }); 106 | var unique = (function unique$(arr) { 107 | /* unique include/functional.sibilant:55:0 */ 108 | 109 | return inject([], arr, (function(coll, item) { 110 | /* include/functional.sibilant:57:13 */ 111 | 112 | return (function() { 113 | if (coll.indexOf(item) !== -1) { 114 | return coll; 115 | } else { 116 | return coll.concat([ item ]); 117 | } 118 | }).call(this); 119 | })); 120 | }); 121 | var interleave = (function interleave$(glue, arr) { 122 | /* interleave include/functional.sibilant:63:0 */ 123 | 124 | (function() { 125 | if ((typeof arr === "string" && (glue && "object" === typeof glue && "Array" === glue.constructor.name))) { 126 | var temp = glue; 127 | glue = arr; 128 | return arr = temp; 129 | } 130 | }).call(this); 131 | return (function() { 132 | if ((glue && "object" === typeof glue && "Array" === glue.constructor.name)) { 133 | return inject([], arr, (function(collector, item, index) { 134 | /* include/functional.sibilant:69:13 */ 135 | 136 | return collector.concat([ item, glue[index] ]); 137 | })); 138 | } else { 139 | return inject([ arr[0] ], arr.slice(1), (function(collector, item, index) { 140 | /* include/functional.sibilant:73:13 */ 141 | 142 | return collector.concat([ glue, item ]); 143 | })); 144 | } 145 | }).call(this); 146 | }); 147 | var flatten = (function flatten$(items, predicate) { 148 | /* flatten include/functional.sibilant:76:0 */ 149 | 150 | return (function() { 151 | if ((items && "object" === typeof items && "Array" === items.constructor.name)) { 152 | return inject([], items, (function(collector, item) { 153 | /* include/functional.sibilant:79:17 */ 154 | 155 | return (function() { 156 | if ((!(predicate) || predicate(item))) { 157 | return collector.concat((function() { 158 | if ((item && "object" === typeof item && "Array" === item.constructor.name)) { 159 | return flatten(item, predicate); 160 | } else { 161 | return item; 162 | } 163 | }).call(this)); 164 | } else { 165 | return collector; 166 | } 167 | }).call(this); 168 | })); 169 | } else if ((!(predicate) || predicate(items))) { 170 | return [ items ]; 171 | } else { 172 | return []; 173 | } 174 | }).call(this); 175 | }); 176 | var flatCompact = (function flatCompact$(items) { 177 | /* flat-compact include/functional.sibilant:89:0 */ 178 | 179 | return flatten(items, (function(item) { 180 | /* include/functional.sibilant:90:20 */ 181 | 182 | return (null !== item && false !== item && typeof item !== "undefined"); 183 | })); 184 | }); 185 | var recurseMap = (function recurseMap$(item, fn) { 186 | /* recurse-map include/functional.sibilant:96:0 */ 187 | 188 | return (function() { 189 | if ((item && "object" === typeof item && "Array" === item.constructor.name)) { 190 | return map(item, (function(subitem) { 191 | /* include/functional.sibilant:97:32 */ 192 | 193 | return recurseMap(subitem, fn); 194 | })); 195 | } else { 196 | return fn(item); 197 | } 198 | }).call(this); 199 | }); 200 | var pluck = (function pluck$(items, attribute) { 201 | /* pluck include/functional.sibilant:100:0 */ 202 | 203 | return map(items, (function(item) { 204 | /* include/functional.sibilant:101:16 */ 205 | 206 | return item[attribute]; 207 | })); 208 | }); 209 | var mergeInto = (function mergeInto$(into, from) { 210 | /* merge-into include/functional.sibilant:103:0 */ 211 | 212 | return Object.assign(into, from); 213 | }); 214 | var clone = (function clone$(object) { 215 | /* clone include/functional.sibilant:106:0 */ 216 | 217 | return Object.assign({ }, object); 218 | }); 219 | var values = (function values$(object) { 220 | /* values include/functional.sibilant:109:0 */ 221 | 222 | return map(Object.keys(object), (function() { 223 | /* include/functional.sibilant:110:26 */ 224 | 225 | return object[arguments[0]]; 226 | })); 227 | }); 228 | var mapValues = (function mapValues$(object, fn) { 229 | /* map-values include/functional.sibilant:112:0 */ 230 | 231 | return inject({ }, Object.keys(object), (function(collector, key, index) { 232 | /* include/functional.sibilant:114:13 */ 233 | 234 | collector[key] = fn(object[key], key); 235 | return collector; 236 | })); 237 | }); 238 | var mergeWith = (function mergeWith$(into, from) { 239 | /* merge-with include/functional.sibilant:118:0 */ 240 | 241 | return Object.assign({ }, into, from); 242 | }); 243 | var extractOptions = (function extractOptions$(config, args) { 244 | /* extract-options src/options.sibilant:3:0 */ 245 | 246 | args = (typeof args !== "undefined") ? args : process.argv.slice(2); 247 | var defaultLabel = "unlabeled", 248 | currentLabel = defaultLabel, 249 | afterBreak = false, 250 | config = (config || { }), 251 | unlabeled = []; 252 | var label__QUERY = (function label__QUERY$(item) { 253 | /* label? src/options.sibilant:11:5 */ 254 | 255 | return (typeof item === "string" && (new RegExp("^-", undefined)).test(item)); 256 | }); 257 | var synonymLookup = (function synonymLookup$(item) { 258 | /* synonym-lookup src/options.sibilant:13:5 */ 259 | 260 | var configEntry = config[item]; 261 | return (function() { 262 | if (typeof configEntry === "string") { 263 | return synonymLookup(configEntry); 264 | } else { 265 | return item; 266 | } 267 | }).call(this); 268 | }); 269 | var takesArgs__QUERY = (function takesArgs__QUERY$(item) { 270 | /* takes-args? src/options.sibilant:19:5 */ 271 | 272 | return false !== config[labelFor(item)]; 273 | }); 274 | defaultLabel = synonymLookup(defaultLabel); 275 | currentLabel = defaultLabel; 276 | var labelFor = (function labelFor$(item) { 277 | /* label-for src/options.sibilant:25:5 */ 278 | 279 | return synonymLookup(item.replace((new RegExp("^-+", undefined)), "")); 280 | }); 281 | var addValue = (function addValue$(hash, key, value) { 282 | /* add-value src/options.sibilant:28:5 */ 283 | 284 | var currentValue = hash[key]; 285 | (function() { 286 | if (typeof currentValue === "undefined") { 287 | currentValue = []; 288 | return hash[key] = currentValue; 289 | } 290 | }).call(this); 291 | return (function() { 292 | if (true !== value) { 293 | return currentValue.push(value); 294 | } 295 | }).call(this); 296 | }); 297 | var resetLabel = (function resetLabel$() { 298 | /* reset-label src/options.sibilant:36:5 */ 299 | 300 | return currentLabel = defaultLabel; 301 | }); 302 | return inject({ }, args, (function(returnHash, item, index) { 303 | /* src/options.sibilant:40:13 */ 304 | 305 | (function() { 306 | if ("--" === item) { 307 | return afterBreak = true; 308 | } else { 309 | return (function() { 310 | if (afterBreak) { 311 | return addValue(returnHash, "afterBreak", item); 312 | } else { 313 | return (function() { 314 | if (label__QUERY(item)) { 315 | currentLabel = labelFor(item); 316 | addValue(returnHash, currentLabel, true); 317 | return (function() { 318 | if (!(takesArgs__QUERY(item))) { 319 | return resetLabel(); 320 | } 321 | }).call(this); 322 | } else { 323 | addValue(returnHash, currentLabel, item); 324 | return resetLabel(); 325 | } 326 | }).call(this); 327 | } 328 | }).call(this); 329 | } 330 | }).call(this); 331 | return returnHash; 332 | })); 333 | }); 334 | var processOptions = (function processOptions$(config) { 335 | /* process-options src/options.sibilant:54:0 */ 336 | 337 | var options = extractOptions(config); 338 | (function() { 339 | if (config) { 340 | var handlePair = (function handlePair$(key, value) { 341 | /* handle-pair src/options.sibilant:57:11 */ 342 | 343 | var handle = config[key]; 344 | (function() { 345 | if (typeof handle === "string") { 346 | return handlePair(handle, value); 347 | } 348 | }).call(this); 349 | return (function() { 350 | if (typeof handle === "function") { 351 | return handle(value, options); 352 | } 353 | }).call(this); 354 | }); 355 | return Object.keys(options).forEach((function(key) { 356 | /* src/options.sibilant:61:11 */ 357 | 358 | return handlePair(key, options[key]); 359 | })); 360 | } 361 | }).call(this); 362 | return options; 363 | }); 364 | module.exports = processOptions; -------------------------------------------------------------------------------- /lib/repl.js: -------------------------------------------------------------------------------- 1 | require("source-map-support").install(); 2 | //# sourceMappingURL=../maps/repl.map 3 | ; 4 | var sibilant = require("./sibilant"), 5 | cardinal = require("cardinal"), 6 | util = require("util"), 7 | vm = require("vm"), 8 | fs = require("fs"); 9 | var input = process.openStdin(), 10 | output = process.stdout, 11 | readline = require("readline").createInterface(input, output), 12 | context = undefined, 13 | cmdBuffer = "", 14 | HISTORY_FILE = (process.env.SIBILANT_REPL_HISTORY_FILE || ("" + process.env.HOME + "/.sibilant.history")), 15 | fd = undefined; 16 | fs.access(HISTORY_FILE, fs.R_OK, (function(err) { 17 | /* src/repl.sibilant:18:9 */ 18 | 19 | return (function() { 20 | if (!(err)) { 21 | return readline.history = fs.readFileSync(HISTORY_FILE, "utf-8").split("\n\n").reverse().filter((function() { 22 | /* src/repl.sibilant:23:31 */ 23 | 24 | return (!!(arguments[0])); 25 | })); 26 | } 27 | }).call(this); 28 | })); 29 | fd = fs.openSync(HISTORY_FILE, "a"); 30 | var createContext = (function createContext$() { 31 | /* create-context src/repl.sibilant:30:0 */ 32 | 33 | var context = vm.createContext(); 34 | module.filename = (process.cwd() + "/exec"); 35 | context._sibilant = sibilant; 36 | context.module = module; 37 | context.require = require; 38 | Object.keys(global).forEach((function(key) { 39 | /* src/repl.sibilant:37:5 */ 40 | 41 | return context[key] = global[key]; 42 | })); 43 | return context; 44 | }); 45 | context = createContext(); 46 | var displayPrompt = (function displayPrompt$() { 47 | /* display-prompt src/repl.sibilant:42:0 */ 48 | 49 | var open = cmdBuffer.split((new RegExp("[\\{\\[\\(]", "g"))).length, 50 | closed = cmdBuffer.split((new RegExp("[\\}\\]\\)]", "g"))).length, 51 | indentation = ""; 52 | (function() { 53 | var while$3 = undefined; 54 | while (open > closed) { 55 | while$3 = (function() { 56 | indentation = (" " + indentation); 57 | return ((open)--); 58 | }).call(this); 59 | }; 60 | return while$3; 61 | }).call(this); 62 | readline.setPrompt((function() { 63 | if (0 === cmdBuffer.length) { 64 | return "sibilant> "; 65 | } else { 66 | return (" " + indentation); 67 | } 68 | }).call(this)); 69 | return readline.prompt(); 70 | }); 71 | var handleLine = (function handleLine$(cmd) { 72 | /* handle-line src/repl.sibilant:57:0 */ 73 | 74 | var jsLine = ""; 75 | (function() { 76 | try { 77 | cmdBuffer = (cmdBuffer + cmd); 78 | js = (sibilant(cmdBuffer)).js; 79 | var safeJs = (function() { 80 | if (js[0] === "{") { 81 | return sibilant.outputFormatter(sibilant.transpile(sibilant.resolveMacro("scoped")(js))); 82 | } else { 83 | return js; 84 | } 85 | }).call(this); 86 | (function() { 87 | try { 88 | return console.log(cardinal.highlight(js)); 89 | } catch (e) { 90 | return console.dir(js); 91 | } 92 | }).call(this); 93 | var result = vm.runInContext(safeJs, context, "sibilant-repl"); 94 | readline.history[0] = cmdBuffer; 95 | fs.writeSync(fd, ("" + cmdBuffer + "\n\n")); 96 | (function() { 97 | if (typeof result !== "undefined") { 98 | return output.write(("result: " + util.inspect(result, { colors: true }) + "\n")); 99 | } 100 | }).call(this); 101 | context._ = result; 102 | return cmdBuffer = ""; 103 | } catch (e) { 104 | return (function() { 105 | if (e.message.match((new RegExp("unclosed node", undefined)))) { 106 | cmdBuffer = (cmdBuffer + "\n"); 107 | return readline.history.shift(); 108 | } else { 109 | readline.history[0] = cmdBuffer; 110 | fs.writeSync(fd, ("" + cmdBuffer + "\n\n")); 111 | output.write((e.stack + "\n")); 112 | return cmdBuffer = ""; 113 | } 114 | }).call(this); 115 | } 116 | }).call(this); 117 | return displayPrompt(); 118 | }); 119 | readline.on("line", handleLine); 120 | readline.on("close", (function() { 121 | /* src/repl.sibilant:98:20 */ 122 | 123 | fs.closeSync(fd); 124 | output.write("\nexiting"); 125 | return input.destroy(); 126 | })); 127 | displayPrompt(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sibilant", 3 | "version": "0.5.6", 4 | "keywords": [ "lisp", "javascript", "language" ], 5 | "description": "javascript with a lisp", 6 | "contributors": [ "Jacob Rothstein (http://jbr.me)", "Matthew Phillips (http://www.matthewphillips.info/)", "Yuest Wang (http://yue.st/)", "Lyndon Tremblay (http://www.hoovy.org)", "David Sargeant (https://github.com/dubiousdavid)" ], 7 | "repository": { 8 | "type": "git", 9 | "url": "http://github.com/jbr/sibilant.git" 10 | }, 11 | "bugs": { 12 | "mail": "sibilant@librelist.com", 13 | "url": "http://github.com/jbr/sibilant/issues" 14 | }, 15 | "bin": { "sibilant": "./bin/sibilant" }, 16 | "main": "./lib/sibilant.js", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "stool": ">=0.0.7", 20 | "diff": ">=2.2.1", 21 | "strip-ansi": ">=3.0.0", 22 | "colors": ">=1.1.2" 23 | }, 24 | "dependencies": { 25 | "source-map": ">=0.5.3", 26 | "source-map-support": ">=0.3.3", 27 | "cardinal": ">=0.6.0" 28 | }, 29 | "scripts": { "test": "bin/sibilant -x stool.sibilant -- test" } 30 | } -------------------------------------------------------------------------------- /package.son: -------------------------------------------------------------------------------- 1 | { name 'sibilant 2 | version (quote (meta (require! {read-file-sync} 'fs) 3 | (|> (read-file-sync "./version" 'utf8) 4 | (replace "\n$" "")))) 5 | keywords ['lisp 'javascript 'language] 6 | description "javascript with a lisp" 7 | 8 | contributors [ "Jacob Rothstein (http://jbr.me)" 9 | "Matthew Phillips (http://www.matthewphillips.info/)" 10 | "Yuest Wang (http://yue.st/)" 11 | "Lyndon Tremblay (http://www.hoovy.org)" 12 | "David Sargeant (https://github.com/dubiousdavid)" ] 13 | 14 | repository { type 'git 15 | url "http://github.com/jbr/sibilant.git" } 16 | 17 | bugs { mail "sibilant@librelist.com" 18 | url "http://github.com/jbr/sibilant/issues" } 19 | 20 | bin { sibilant "./bin/sibilant" } 21 | main "./lib/sibilant.js" 22 | license "MIT" 23 | 24 | dev-dependencies { stool ">=0.0.7" 25 | diff ">=2.2.1" 26 | "strip-ansi" ">=3.0.0" 27 | colors ">=1.1.2" } 28 | 29 | dependencies { "source-map" ">=0.5.3" 30 | "source-map-support" ">=0.3.3" 31 | cardinal ">=0.6.0" } 32 | 33 | scripts { test "bin/sibilant -x stool.sibilant -- test" }} 34 | -------------------------------------------------------------------------------- /public/github-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbr/sibilant/0ae34cbecdbe3fbe0dff349d6a41a88a86732ce8/public/github-150.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Sibilant: Javascript with a LISP 24 | 25 | 26 |
27 |

(Sibilant: JavaScript with a LISP)

28 |
29 | github.com/jbr/sibilant 31 |
32 | 33 |
34 |

Welcome!

35 |

36 | Sibilant is an s-expression language that compiles to readable and 37 | idiomatic JavaScript. Sibilant is built on a simple macro system 38 | that gives you compile-time control over the output JavaScript 39 | as well as providing tools to smooth over some of JavaScript's 40 | historical idiosynchracies. 41 |

42 | 43 |

If you'd like to follow along in a local REPL, 44 |

bash> npm install -g sibilant
 45 | bash> sibilant
 46 | sibilant> (console.log "welcome to sibilant")
 47 | console.log("welcome to sibilant")
 48 | welcome to sibilant
 49 |       
50 |

51 | 52 |

53 | All of the code in the left column for the rest of this document 54 | is editable and is compiled by your browser as you type. 55 |

56 | 57 | 72 | 73 |

74 | Here's an quick sample of sibilant code (inspired by the first 75 | example on coffeescript.org). 76 |

77 | 78 | 98 |

99 | And here's the canonical node example 100 | from nodejs.org 101 |

102 | 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 |
119 |

Numbers and Strings

120 |

121 | Numbers should look pretty familiar. Use commas to enhance 122 | readability. 123 |

124 | 127 |

128 | Strings are surrounded by double quotes. Multi-line strings are 129 | supported! Use a backslash to escape a double-quote inside of a 130 | string. 131 |

132 | 137 |
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 |
146 |

Identifiers

147 |

148 | Variable names may include letters, 149 | the period (.) and the hyphen (-). 150 | Lower case letters are idiomatic. 151 | They may end with a question mark (?) or with a 152 | bang (!). They may start with a sigil ($). 153 |

154 | 163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 |
173 |

Objects and Arrays

174 |

175 | Objects and Arrays are supported as a proper subset of JSON. 176 |

177 | 184 |

185 | Idiomatic sibilant skips any unnecessary commas and colons that do 186 | not contribute to readability 187 |

188 | 194 | 195 |

Arrays and objects contents are accessed with the get and set macros

196 | 201 |
202 | 203 | 204 | 205 | 206 | 207 |
208 |

Defining variables

209 |

210 | Since sibilant is a tool for writing JavaScript, it exposes the var 211 | keyword with an identically named macro. 212 |

213 | 214 | 218 |

To modify an existing variable (assignment), use the assign macro.

219 | 220 |
221 | 222 | 223 | 224 | 225 |
226 |

Defining functions

227 |

228 | Sibilant avoids hoisiting by defining functions as variable by 229 | default. 230 |

231 | 237 | 238 |

239 | If your function name includes a dot, it will not be defined as a 240 | variable. 241 |

242 | 247 |
248 | 249 | 250 | 251 |
252 |

Lambdas and Thunks

253 |

254 | Lambdas are how sibilant defines anonymous functions. 255 |

256 | 263 |

264 | Because anonymous functions are is used so often in JavaScript, 265 | sibilant includes a shortcut to define lambdas, #. 266 |

267 | 268 |

269 | Thunks are zero-arity lambdas (anonymous functions that accept no 270 | arguments). A shortcut for this is the #> macro. 271 |

272 | 277 |
278 | 279 | 280 | 281 | 282 | 283 |
284 |

Conditionals

285 |

286 | Sibilant provides two primary conditional macros: if and when. When 287 | is the simplest, only executing the subsequent block when the 288 | conditional evaluates to a truthy value. All conditionals in 289 | sibilant are expressions and evaluate to some value. This is done 290 | by introducing a scope with a self-executing function. 291 |

292 | 297 |

298 | The `if` macro supports any number of branching paths. If the bodies 299 | of the branching paths needs more than one expression, the `do` 300 | macro is used. 301 |

302 | 311 |
312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 |
322 |

Iteration

323 |

324 | Iteration is an example of a macro that can easily be redefined for 325 | different compilation contexts. Since the default compilation 326 | environments are modern browsers and node, the `each` macro compiles 327 | to `[].forEach`. If you needed to compile sibilant to an older 328 | JavaScript, the each macro could be easily modified to support a 329 | `for` loop. 330 |

331 | 332 | 339 |
340 | 341 | 342 |
343 |

Further Reading

344 |

345 | For further documentation, check 346 | out docs.sibilant.org and ask questions on gitter or github issues. 347 |

348 |
349 | 350 | 351 |
352 | 353 | 354 | 355 | 356 | 357 | 368 | 369 | 370 | -------------------------------------------------------------------------------- /public/javascripts/browser.js: -------------------------------------------------------------------------------- 1 | ../../lib/browser.js -------------------------------------------------------------------------------- /public/javascripts/browser.map: -------------------------------------------------------------------------------- 1 | ../../maps/browser.map -------------------------------------------------------------------------------- /public/javascripts/jquery.js: -------------------------------------------------------------------------------- 1 | jquery-2.1.4.min.js -------------------------------------------------------------------------------- /public/javascripts/jquery.map: -------------------------------------------------------------------------------- 1 | jquery-2.1.4.min.map -------------------------------------------------------------------------------- /public/javascripts/jquery.scrollNav.min.js: -------------------------------------------------------------------------------- 1 | (function(e){e.fn.scrollNav=function(t){e("body").addClass("sn-loading");var n={sections:"h3",titleText:"Scroll To",fixedMargin:40,animated:!0,speed:500,showHeadline:!0,showTopLink:!0,location:"insertBefore"};e.extend(n,t);var r=[],i=this,s=i.find(n.sections),o=e("