├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── arc.js ├── arc.min.js ├── arc_loader.js ├── bin ├── arcjs └── arcjsc ├── demo ├── demo1.arc ├── demo1.html ├── repl.css ├── repl.html ├── repl.js ├── stack_visualizer.css ├── stack_visualizer.html ├── stack_visualizer.js ├── web_defs.arc └── web_server.js ├── docs ├── Makefile ├── README.md ├── requirements.txt └── source │ ├── _static │ ├── arc.js │ ├── arc.min.js │ ├── arc_loader.js │ ├── avg.js.fasl │ ├── fasl_example.html │ ├── fizzbuzz.html │ ├── hw.html │ ├── main.js │ ├── reversi.arc │ ├── reversi.html │ └── reversi_bridge.js │ ├── conf.py │ ├── index.rst │ ├── refs.rst │ └── tutorial.rst ├── lib ├── chai │ └── chai.js ├── classify.js ├── classify.simple.js ├── codemirror │ ├── addon │ │ └── edit │ │ │ └── matchbrackets.js │ ├── keymap │ │ └── emacs.js │ ├── lib │ │ ├── codemirror.css │ │ └── codemirror.js │ ├── mode │ │ └── clojure │ │ │ └── clojure.js │ └── theme │ │ └── ambiance.css ├── jasmine-1.3.1 │ ├── MIT.LICENSE │ ├── jasmine-html.js │ ├── jasmine.css │ └── jasmine.js ├── jquery-1.7.2.min.js └── mocha │ ├── mocha.css │ └── mocha.js ├── package.json ├── src ├── arc.fasl ├── arc.js ├── arc │ ├── arc.arc │ ├── compiler.arc │ ├── core.arc │ └── unit.arc ├── box.js ├── call.js ├── char.js ├── closure.js ├── comments.js ├── compiler.fasl ├── cons.js ├── context.js ├── continuation.js ├── core.fasl ├── namespace.js ├── operators.js ├── preload.js ├── primitives.js ├── primitives │ ├── collection.js │ ├── core.js │ ├── math.js │ └── time.js ├── reader.js ├── regexp.js ├── stack.js ├── symbol.js ├── table.js ├── tagged.js ├── unit.fasl └── vm.js ├── test ├── compiling-compiler.html ├── compiling-compiler.js ├── unit.html └── unit │ ├── arc │ ├── core.arc │ └── ns.arc │ └── impl.js └── tools ├── arc-compiler-arc ├── helper-compiler ├── compiler-file.arc ├── compiler-server.arc ├── compiler.arc ├── test-vm.arc └── util.arc ├── jsconstruct ├── run-compiler-server └── update-watcher /.gitignore: -------------------------------------------------------------------------------- 1 | memo* 2 | *memo 3 | backup/ 4 | copy.sh 5 | _site/ 6 | docs/build/ 7 | docs/env/ 8 | node_modules/ 9 | arc.min.js.gz -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.11" 4 | - "0.10" 5 | branches: 6 | only: 7 | - master -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ### ArcJS 2 | 3 | Copyright (c) 2012 Shin Aoyama 4 | 5 | ----------------- 6 | 7 | Perl Foundations's Artistic License 2.0 8 | 9 | 10 | ### Arc language 11 | 12 | Copyright (c) Paul Graham 13 | Copyright (c) Robert Morris 14 | 15 | ----------------- 16 | 17 | Perl Foundations's Artistic License 2.0 18 | 19 | 20 | ### Anarki 21 | 22 | Copyright (c) Paul Graham 23 | Copyright (c) Robert Morris 24 | 25 | Copyright (c) A lot of contributors (see https://github.com/arclanguage/anarki/graphs/contributors) 26 | 27 | ----------------- 28 | 29 | Perl Foundations's Artistic License 2.0 -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | COMPRESS=node_modules/uglify-js/bin/uglifyjs 2 | CONSTRUCT=tools/jsconstruct 3 | COMPILE_ARC=bin/arcjsc 4 | DATETIME=$(shell date +'%Y%m%d%H%M%S') 5 | BUILDDIR=. 6 | CURRENT_BRANCH=$(shell git branch | grep \* | sed -e "s/^\* //") 7 | UNIT_TESTS=$(shell ls test/unit/arc/*.arc) 8 | 9 | all: arc.js arc.min.js arc.min.js.gz 10 | 11 | noeval: arc_noeval.js arc.min.js arc.min.js.gz 12 | 13 | clean: 14 | rm -f arc.js arc.min.js arc.min.js.gz 15 | 16 | test: arc.min.js $(UNIT_TESTS) 17 | npm test 18 | 19 | auto: 20 | make 21 | ./tools/update-watcher src/*.js src/arc/*.arc -- make 22 | 23 | arc.js: src/*.js src/primitives/*.js src/*.fasl 24 | $(CONSTRUCT) -o arc.tmp.js src/arc.js 25 | cat src/comments.js arc.tmp.js > arc.js 26 | rm arc.tmp.js 27 | 28 | arc_noeval.js: src/*.js src/primitives/*.js src/*.fasl 29 | NO_EVAL=yes $(CONSTRUCT) -o arc.tmp.js src/arc.js 30 | cat src/comments.js arc.tmp.js > arc.js 31 | rm arc.tmp.js 32 | 33 | arc.min.js: arc.js 34 | $(COMPRESS) --unsafe -nc -o arc.min.js arc.js 35 | 36 | arc.min.js.gz: arc.min.js 37 | gzip -k -f arc.min.js 38 | 39 | arc: src/arc/arc.arc 40 | $(COMPILE_ARC) -d -o src/arc.fasl src/arc/arc.arc 41 | 42 | compiler: src/arc/compiler.arc 43 | mkdir -p backup 44 | if [ -e src/compiler.fasl ]; then cp src/compiler.fasl backup/$(DATETIME).compiler.fasl; fi; 45 | $(COMPILE_ARC) -d -o src/compiler.fasl src/arc/compiler.arc 46 | 47 | core: src/arc/core.arc 48 | mkdir -p backup 49 | if [ -e src/core.fasl ]; then cp src/core.fasl backup/$(DATETIME).core.fasl; fi; 50 | $(COMPILE_ARC) -d -o src/core.fasl src/arc/core.arc 51 | 52 | arc-unit: src/arc/unit.arc 53 | mkdir -p backup 54 | if [ -e src/unit.fasl ]; then cp src/unit.fasl backup/$(DATETIME).unit.fasl; fi; 55 | $(COMPILE_ARC) -d -o src/unit.fasl src/arc/unit.arc 56 | 57 | restore_compiler: 58 | mv $(shell ls backup/*.compiler.fasl | sort -r | sed '1!d') src/compiler.fasl 59 | make 60 | 61 | install_web: arc.min.js 62 | cp arc.js arc.js.bk 63 | cp arc.min.js arc.min.js.bk 64 | git checkout gh-pages 65 | mv arc.js.bk js/arc.js 66 | mv arc.min.js.bk js/arc.min.js 67 | git add js/ 68 | git commit -m 'Installed new arc.js.' 69 | git push origin gh-pages 70 | git checkout $(CURRENT_BRANCH) 71 | rm -f arc.js.bk arc.min.js.bk 72 | 73 | setup: 74 | npm install uglify-js 75 | npm install mocha 76 | npm install chai 77 | 78 | doc: 79 | cp arc.js docs/source/_static/arc.js 80 | cp arc.min.js docs/source/_static/arc.min.js 81 | cp arc_loader.js docs/source/_static/arc_loader.js 82 | cd docs && make html 83 | 84 | doc_clean: 85 | cd docs && make clean 86 | 87 | .PHONY: all clean 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### ArcJS 2 | 3 | [![Build Status](https://travis-ci.org/smihica/arc-js.svg?branch=master)](https://travis-ci.org/smihica/arc-js) 4 | [![Docs](https://readthedocs.org/projects/arcjs/badge/?version=latest)](http://arcjs.readthedocs.org/en/latest/) 5 | 6 | __An Arc-langugage compiler and VM-interpreter written in JavaScript__ 7 | 8 | Arc-language can run both on nodejs and on a web-site. 9 | You can get more information from the [website](http://smihica.github.io/arc-js/) 10 | or [documentation](http://arcjs.readthedocs.org/en/latest/). 11 | 12 | A lot of inspired from Paul Graham version of [Arc](http://arclanguage.org/) and [Anarki](https://github.com/arclanguage/anarki) 13 | 14 | ### Demo 15 | 16 | #### client side 17 | 18 | 1. [REPL](http://smihica.github.io/arc-js/demo_repl.html) 19 | 2. [Maze generator](http://smihica.github.io/arc-js/demo_mg.html) 20 | 3. [Strange attractor generator](http://smihica.github.io/arc-js/demo_at.html) 21 | 4. [Automatic reversi player](http://smihica.github.io/arc-js/reversi.html) 22 | 5. [Tetris](http://smihica.github.io/arc-js/demo_tetris.html) 23 | 24 | ### How to make 25 | 26 | #### install Node.js and npm (on mac) 27 | 28 | # from port 29 | $ sudo port install nodejs 30 | 31 | # or from brew 32 | $ brew install node.js 33 | 34 | #### setup the compressor and unit-test framework. 35 | 36 | $ make setup 37 | 38 | #### make ArcJS 39 | 40 | $ make 41 | 42 | ### How to run tests 43 | 44 | $ make test 45 | 46 | ### How to run repl 47 | 48 | $ ./bin/arcjs 49 | arc> (+ 1 2 3) 50 | 6 51 | arc> (for n 1 100 52 | (prn (case (gcd n 15) 53 | 1 n 54 | 3 'Fizz 55 | 5 'Buzz 56 | 'FizzBuzz))) 57 | 1 58 | 2 59 | Fizz 60 | ... 61 | arc> (def average (x y) (/ (+ x y) 2)) 62 | # 63 | arc> (average 2 4) 64 | 3 65 | 66 | Try Arc's [tutorial](http://ycombinator.com/arc/tut.txt) 67 | 68 | ### How to run scripts 69 | 70 | $ echo "(prn (gcd 33 77))" > test.arc 71 | $ ./bin/arcjs test.arc 72 | 11 73 | 74 | ### How to run repl with preloading some scripts 75 | 76 | $ echo "(def average (x y) (/ (+ x y) 2))" > avg.arc 77 | $ ./bin/arcjs -l avg.arc 78 | arc> (average 10 20) 79 | 15 80 | 81 | ### How to run compiler 82 | 83 | $ echo "(def average (x y) (/ (+ x y) 2))" > avg.arc 84 | $ ./bin/arcjsc -o avg.js.fasl avg.arc 85 | $ cat avg.js.fasl 86 | // This is an auto generated file. 87 | // Compiled from ['avg.arc']. 88 | // DON'T EDIT !!! 89 | preloads.push([ 90 | [12,7,14,20,0,1,0,20,2,-1,0,10,9,1, ... 91 | ]); 92 | preload_vals.push(["2","+","/", ... 93 | $ 94 | 95 | ### License 96 | 97 | # ArcJS 98 | 99 | Copyright (c) 2012 Shin Aoyama 100 | ----------------- 101 | Perl Foundations's Artistic License 2.0 102 | 103 | # Arc language 104 | 105 | Copyright (c) Paul Graham 106 | Copyright (c) Robert Morris 107 | ----------------- 108 | Perl Foundations's Artistic License 2.0 109 | 110 | # Anarki 111 | 112 | Copyright (c) Paul Graham 113 | Copyright (c) Robert Morris 114 | Copyright (c) A lot of contributors (see https://github.com/arclanguage/anarki/graphs/contributors) 115 | ----------------- 116 | Perl Foundations's Artistic License 2.0 117 | -------------------------------------------------------------------------------- /arc_loader.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | var runner = ArcJS.context(); 3 | var codes = $('script[type="text/arc"]').map(function(i, v) { 4 | var inner = v.innerText; 5 | var src = v.src; 6 | return {script: inner, src: src}; 7 | }); 8 | var fasls = $('script[type="text/arc-fasl"]').map(function(i, v) { 9 | var inner = v.innerText; 10 | var src = v.src; 11 | return {script: inner, src: src}; 12 | }); 13 | 14 | function iter(codes, i, type, after) { 15 | if (i < codes.length) { 16 | var script = codes[i].script 17 | var src = codes[i].src; 18 | if (src) { 19 | $.ajax({ 20 | url: src, 21 | dataType: 'text' 22 | }).done(function(data){ 23 | var fasl; 24 | switch(type) { 25 | case 'fasl': 26 | eval('var fasl = (function() {\nvar preloads = [], preload_vals = [];\n' + 27 | data + 28 | 'return {preloads: preloads, preload_vals: preload_vals};\n})();'); 29 | ArcJS.fasl_loader(ArcJS.NameSpace.get('user'), fasl.preloads, fasl.preload_vals); 30 | break; 31 | case 'arc': 32 | runner.evaluate(data); 33 | break; 34 | } 35 | if (script) runner.evaluate(script); 36 | iter(codes, i+1, type, after); 37 | }); 38 | } else { 39 | if (script) runner.evaluate(script); 40 | iter(codes, i+1, type, after); 41 | } 42 | } else { 43 | if (after) after(); 44 | } 45 | } 46 | 47 | iter(fasls, 0, 'fasl', function() { 48 | iter(codes, 0, 'arc'); 49 | }); 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /bin/arcjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var term = 'arc> '; 5 | var readline = require('readline'); 6 | var ArcJS = require('../arc.js'); 7 | var runner = ArcJS.context(); 8 | var vm = runner.vm; 9 | 10 | var rl = readline.createInterface({ 11 | input: process.stdin, 12 | output: process.stdout, 13 | terminal: false 14 | }); 15 | 16 | function compile(expr) { 17 | var asm = [ 18 | ['frame', 8], 19 | ['constant', expr], 20 | ['argument'], 21 | ['constant', 1], 22 | ['argument'], 23 | ['refer-global', 'compile'], 24 | ['indirect'], 25 | ['apply'], 26 | ['halt'] 27 | ]; 28 | vm.cleanup(); 29 | vm.set_asm(asm); 30 | return vm.run(); 31 | } 32 | 33 | var code_hist = ''; 34 | function onenter(code) { 35 | var expr = null, res = null, result = '', err = 0; 36 | if ((code.match(/^\s*$/)) && code_hist === '') return false; 37 | 38 | var code_all = code_hist + code; 39 | 40 | do { 41 | 42 | try { 43 | expr = vm.reader.read(code_all); 44 | if (expr === ArcJS.Reader.EOF) return false; 45 | } catch (e) { 46 | if (vm.reader.i < vm.reader.slen) { 47 | result = "Reader" + e.toString(); 48 | err = 1; 49 | } 50 | else { /* Not closed yet. ignore.*/ 51 | code_hist = code_all; 52 | return true; 53 | } 54 | } 55 | if (result === ArcJS.Reader.EOF) { 56 | if (code_hist === '') { 57 | return false; 58 | } else { 59 | code_hist = code_all; 60 | return true; 61 | } 62 | } 63 | if (err === 0) { 64 | var called_ns = vm.ns; 65 | var called_current_ns = vm.current_ns; 66 | try { 67 | var compiled = compile(expr); 68 | vm.cleanup(); 69 | vm.load(compiled); 70 | res = vm.run(); 71 | result = ArcJS.stringify(res); 72 | } catch (e) { 73 | result = e.toString(); 74 | vm.ns = called_ns; 75 | vm.current_ns = called_current_ns; 76 | err = 2; 77 | } 78 | } 79 | if (err !== 0) { 80 | process.stderr.write(result + "\n"); 81 | if (err === 2) { // only error in call 82 | var call_stack_str = vm.get_call_stack_string(); 83 | process.stderr.write(call_stack_str + "\n"); 84 | } 85 | } else { 86 | process.stdout.write(result + "\n"); 87 | } 88 | if (vm.warn) { 89 | process.stderr.write(vm.warn + "\n"); 90 | } 91 | 92 | code_hist = ''; 93 | code_all = vm.reader.str.slice(vm.reader.i); 94 | 95 | term = 'arc' + ((vm.current_ns.name !== 'user') ? 96 | ':' + vm.current_ns.name : 97 | '') + '> '; 98 | 99 | } while (code_all !== ''); 100 | 101 | return false; 102 | } 103 | 104 | function main(mode, scripts) { 105 | 106 | (function prepare(i, after) { 107 | if (scripts.length <= i) return after(); 108 | fs.readFile(scripts[i], 'utf8', function(err, data) { 109 | if (err) throw new Error(err); 110 | if (scripts[i].match(/\.fasl$/)) { 111 | eval('var fasl = (function() {\nvar preloads = [], preload_vals = [];\n' + data + 112 | 'return {preloads: preloads, preload_vals: preload_vals};\n})();'); 113 | ArcJS.fasl_loader(ArcJS.NameSpace.get('user'), fasl.preloads, fasl.preload_vals); 114 | } else if (scripts[i].match(/\.js$/)) { 115 | eval('(function(){' + data + '})()'); 116 | } else { 117 | runner.evaluate(data); 118 | } 119 | prepare(i+1, after); 120 | }); 121 | })(0, function after() { 122 | if (mode === 'run') { 123 | vm.set_all_timer_cleared(function(result){ 124 | process.exit(result); 125 | }); 126 | } 127 | 128 | rl.on('line', function (code) { 129 | var continue_flag = onenter(code+'\n'); 130 | if (!continue_flag) process.stdout.write(term); 131 | }); 132 | 133 | if (mode !== 'run') process.stdout.write(term); 134 | 135 | }); 136 | } 137 | 138 | var argv = process.argv.slice(2); 139 | var scripts = []; 140 | var mode = 'repl'; 141 | var arglen = argv.length; 142 | if (0 < arglen) mode = 'run'; 143 | for (var i=0,l=arglen; i 2 | 3 | 4 | 5 | Demo1 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 |

16 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/repl.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | min-height: 100%; 5 | margin: 0; padding: 0; 6 | background: black; 7 | color: white; 8 | } 9 | h1 { 10 | font-family: Arial; 11 | padding-left: 10px; 12 | } 13 | div#repl { 14 | width: 100%; height: 100%; 15 | position: relative; 16 | box-sizing: border-box; 17 | background: black; 18 | color: white; 19 | font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 20 | font-size: 18px; 21 | line-height: 22px; 22 | } 23 | 24 | div#repl-txt { 25 | width: 90%; 26 | position: absolute; 27 | top: 0; left: 10px; 28 | font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 29 | font-size: 18px; 30 | line-height: 22px; 31 | } 32 | 33 | div#holder { 34 | width: 90%; height: 100px; 35 | position: absolute; 36 | left: 50px; 37 | top: 16px; 38 | font-size: 16px; 39 | font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace !important; 40 | } 41 | 42 | div#repl pre.code { 43 | color: #f93; 44 | font-weight: bold; 45 | margin: 0; padding: 0; 46 | font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 47 | font-size: 18px; 48 | line-height: 22px; 49 | } 50 | 51 | span.error { 52 | color: red; 53 | font-weight: bold; 54 | } 55 | 56 | span.time { 57 | color: #777; 58 | } -------------------------------------------------------------------------------- /demo/repl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | arc-js : repl 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demo/repl.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var s = new Date(); 4 | var runner = ArcJS.context(); 5 | var e = new Date(); 6 | 7 | var holder = $('#holder'); 8 | var txt = $('#repl-txt'); 9 | var init_time = e - s; 10 | txt.html(';; ArcJS ' + ArcJS.version + ' ' + ' Initialized in ' + init_time + ' ms
arc>
'); 11 | 12 | var cm = CodeMirror(holder[0], { 13 | value: '', 14 | mode: "clojure", 15 | theme: "ambiance", 16 | matchBrackets: true, 17 | keyMap: 'emacs' 18 | }); 19 | 20 | var escapeHTML = (function() { 21 | var htmlEscapes = { 22 | '&': '&', 23 | '<': '<', 24 | '>': '>', 25 | '"': '"', 26 | "'": ''', 27 | '/': '/' 28 | }; 29 | var htmlEscaper = /[&<>"'\/]/g; 30 | return function(string) { 31 | return ('' + string).replace(htmlEscaper, function(match) { 32 | return htmlEscapes[match]; 33 | }); 34 | } 35 | })(); 36 | 37 | function onenter(code) { 38 | var expr = null, res = null, result = '', err = false; 39 | var read_time = 0, compile_time = 0, eval_time = 0; 40 | if (code.match(/^\s*$/g)) return; 41 | try { 42 | var s = new Date(); 43 | expr = runner.read(code); 44 | var e = new Date(); 45 | read_time = e - s; 46 | } catch (e) { 47 | if (runner.vm.reader.i < runner.vm.reader.slen) { 48 | result = e.toString(); 49 | err = true; 50 | } 51 | else { /* ignore */ return; } 52 | } 53 | cm.setValue(''); 54 | if (!err) { 55 | try { 56 | var s = new Date(); 57 | var compiled = runner.compile(expr); 58 | var e = new Date(); 59 | compile_time = e - s; 60 | var s = new Date(); 61 | res = runner.eval_asm(compiled); 62 | var e = new Date(); 63 | eval_time = e - s; 64 | result = ArcJS.stringify(res); 65 | // console.log(ArcJS.NameSpace.stack); 66 | } catch (e) { 67 | result = e.toString(); 68 | err = true; 69 | } 70 | } 71 | var code_list = code.split('\n').filter(function(x){return x !== ''}).map(escapeHTML); 72 | var result_list = result.split('\n').filter(function(x){return x !== '';}).map(escapeHTML); 73 | var line_len = result_list.length + code_list.length; 74 | var org = txt.html(); 75 | var _new = '
' + code_list.join('
') + '
' + 76 | '' + 77 | ';; past-times read:' + read_time + 78 | 'ms compile:' + compile_time + 79 | 'ms eval:' + eval_time + 80 | 'ms total:' + (read_time + compile_time + eval_time) + 'ms' + '
' + 81 | (function(r){ 82 | if (err) { 83 | var call_stack_arr = runner.vm.get_call_stack_string().split('\n') 84 | var call_stack_str = '
' + call_stack_arr.filter(function(x){return x !== '';}).map(escapeHTML).join('
') + "
"; 85 | line_len += call_stack_arr.length; 86 | return '' + r + call_stack_str + ''; 87 | } 88 | return r; 89 | })(result_list.join('
')); 90 | 91 | var ns = runner.vm.namespace; 92 | var nss = ''; 93 | while (ns !== ArcJS.NameSpace.root) { 94 | nss = '::' + ns.name + nss; 95 | ns = ns.upper; 96 | } 97 | txt.html(org + _new + '
arc' + nss + '>
'); 98 | var pos = holder.position(); 99 | holder.css({ 100 | 'top': pos.top + ((line_len + 1 + 1) * 22), 101 | 'left': 50 + (nss.length * 10) 102 | }); 103 | } 104 | 105 | var last_len = 0; 106 | cm.on('change', function onchange() { 107 | var v = cm.getValue(); 108 | var len = v.length; 109 | if (last_len < len && v[len-1] === '\n') { 110 | cm.off('change', onchange); 111 | onenter(v); 112 | cm.on('change', onchange); 113 | } 114 | last_len = len; 115 | }); 116 | 117 | cm.focus(); 118 | }); 119 | -------------------------------------------------------------------------------- /demo/stack_visualizer.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | min-height: 100%; 4 | height: 100%; 5 | margin: 0; padding: 0; 6 | } 7 | table { 8 | width: 100%; 9 | height: 100%; 10 | border-collapse: collapse; 11 | margin: 0; padding: 0; 12 | } 13 | table tr td { 14 | margin: 0; padding: 0; 15 | overflow: scroll; 16 | width: 33%; 17 | height: 100%; 18 | box-sizing: border-box; 19 | vertical-align: top; 20 | } 21 | table tr td textarea { 22 | margin: 0; padding: 0; 23 | box-sizing: border-box; 24 | width: 100%; 25 | height: 100%; 26 | font-size:16px; 27 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 28 | background-color: #FFF; 29 | } 30 | div#status { 31 | margin: 0; padding: 0; 32 | width: 100%; 33 | height: 5%; 34 | border: 1px solid #000; 35 | font-size:14px; 36 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 37 | } 38 | div#asm { 39 | margin: 0; padding: 0; 40 | width: 100%; 41 | height: 70%; 42 | overflow: scroll; 43 | border: 1px solid #000; 44 | } 45 | #res { 46 | margin: 0; padding: 0; 47 | width: 100%; 48 | height: 25%; 49 | overflow: scroll; 50 | border: 1px solid #000; 51 | font-size:16px; 52 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 53 | } 54 | table th { 55 | text-align: right; 56 | } 57 | 58 | th button { 59 | font-size: 16px; 60 | } 61 | 62 | div#stack { 63 | width: 100%; 64 | height: 100%; 65 | overflow: scroll; 66 | border: 1px solid #000; 67 | } 68 | 69 | div#stack table { 70 | width: 100%; 71 | height: auto; 72 | font-size: 12px; 73 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 74 | } 75 | 76 | div#stack table tr td { 77 | border-bottom: 1px solid #CCC; 78 | color: black; 79 | } 80 | 81 | div#stack table tr td:first-child { 82 | border-right: 1px solid #CCC; 83 | width: 2%; 84 | } 85 | 86 | div#stack table tr.s td { 87 | background: #F99; 88 | } 89 | 90 | div#stack table tr.f td { 91 | background: #99F; 92 | } 93 | 94 | div#stack table tr.l td { 95 | background: #9F9; 96 | } 97 | 98 | div#asm table { 99 | font-size: 12px; 100 | width: 100%; 101 | height: auto; 102 | font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 103 | } 104 | 105 | div#asm table tr td { 106 | border-bottom: 1px solid #CCC; 107 | color: black; 108 | } 109 | 110 | div#asm table tr td:first-child { 111 | border-right: 1px solid #CCC; 112 | width: 2%; 113 | } 114 | 115 | div#asm table tr.p td { 116 | background: #F99; 117 | } -------------------------------------------------------------------------------- /demo/stack_visualizer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | arc-js : stack visualizer 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 32 |
15 | 16 | 17 | 18 | 19 |
27 |
28 |
29 |

30 |       
33 | 34 | 35 | -------------------------------------------------------------------------------- /demo/stack_visualizer.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | var vm = new ArcJS.VM(); 3 | var stringify = ArcJS.stringify; 4 | 5 | function compile_srv() { 6 | $.ajax({ 7 | url: '/arc-compiler', 8 | type: 'POST', 9 | data: { 10 | code: $("#arc").val() 11 | } 12 | }).done(function(res) { 13 | vm.cleanup(); 14 | vm.load_string(res); 15 | show_asm(res); 16 | }).error(function(r) { 17 | alert(r.responseText); 18 | }); 19 | } 20 | 21 | function read_compile() { 22 | var code = $("#arc").val(); 23 | var asm = [ 24 | ['frame', 8], 25 | ['constant', vm.reader.read(code)], 26 | ['argument'], 27 | ['constant', 1], 28 | ['argument'], 29 | ['refer-global', 'do-compile'], 30 | ['indirect'], 31 | ['apply'], 32 | ['halt'] 33 | ]; 34 | vm.cleanup(); 35 | vm.set_asm(asm); 36 | var compiled = vm.run(); 37 | vm.cleanup(); 38 | vm.load(compiled); 39 | show_asm(res); 40 | reset(); 41 | } 42 | 43 | function run() { 44 | var rt; 45 | try { 46 | rt = stringify(vm.run()); 47 | } catch (e) { 48 | $('#res').html(e+'\n'+vm.get_call_stack_string()); 49 | throw e; 50 | } 51 | $('#res').text(rt); 52 | } 53 | 54 | function show_asm(asm) { 55 | var tbl = $(""); 56 | for (var i=0, l=vm.x.length; i"); 58 | if (vm.p == i) tr.addClass('p'); 59 | var td = $(""); 60 | var td2 = $("
" + i + ""); 61 | td2.text(vm.x[i]); 62 | tbl.append(tr.append(td, td2)); 63 | } 64 | $("#asm").html(tbl); 65 | var h = tbl.height(); 66 | var top = ((h / l) * vm.p) 67 | $("#asm").scrollTop(top); 68 | } 69 | 70 | function show_stack() { 71 | var tbl = $(""); 72 | var h = 50; 73 | var stack = vm.stack.stack; 74 | var slen = stack.length; 75 | var top = Math.max(h, slen+1); 76 | for (var i=top; (top-h-1)", 78 | (i == vm.s) ? {class: "s"} : 79 | (i == vm.f) ? {class: "f"} : 80 | (i == vm.l) ? {class: "l"} : {}); 81 | var td = $(""); 82 | var td2 = $("
" + i + ""); 83 | td2.text(((i < slen) ? (stringify(stack[i])+'').slice(0, 50) : ' ---- ')); 84 | tbl.append(tr.append(td, td2)); 85 | } 86 | $("#stack").html(tbl); 87 | var scroll_top = ((tbl.height() / (h + 1)) * (h - vm.s)); 88 | $("#stack").scrollTop(scroll_top); 89 | } 90 | 91 | function show_status() { 92 | $("#status").text( 93 | ("[" + vm.count + "] " + 94 | " a: " + (stringify(vm.a)+'').slice(0, 30) + 95 | " f: " + vm.f + 96 | " l: " + vm.l + 97 | " c: " + vm.c + 98 | " s: " + vm.s)); 99 | } 100 | 101 | function step() { 102 | var rt; 103 | try { 104 | rt = vm.step(); 105 | } catch (e) { 106 | $('#res').html(e+'\n'+vm.get_call_stack_string()); 107 | throw e; 108 | } 109 | show_stack(); 110 | show_asm(); 111 | show_status(); 112 | if (rt !== void(0)) 113 | $('#res').text(stringify(rt)); 114 | } 115 | 116 | function reset() { 117 | vm.cleanup(); 118 | show_stack(); 119 | show_asm(); 120 | show_status(); 121 | } 122 | 123 | $("#read-compile-btn").click(read_compile); 124 | $("#compile-srv-btn").click(compile_srv); 125 | $("#run-btn").click(run); 126 | $("#step-btn").click(step); 127 | $("#reset-btn").click(reset); 128 | 129 | $("#arc").val( 130 | ("(def fib (n)\n" + 131 | " (if (< n 2)\n"+ 132 | " n\n" + 133 | " (+ (fib (- n 1)) (fib (- n 2)))))\n\n; (fib 10)")); 134 | 135 | read_compile(); 136 | }); 137 | 138 | -------------------------------------------------------------------------------- /demo/web_defs.arc: -------------------------------------------------------------------------------- 1 | (ns (defns "user.server")) 2 | 3 | (= *url* (table)) 4 | 5 | ;; entry point from js. 6 | (def exec-url (uri method data headers) 7 | (pair 8 | (aif (*url* (list method uri)) 9 | (list "code" 200 10 | "body" (apply it data headers) 11 | "Content-Type" "text/html") 12 | (list "code" 404 13 | "body" (+ uri " is not Found.") 14 | "Content-Type" "text/plain")))) 15 | 16 | (def simple-render (lis) 17 | ;; '(html (body (h1 "x"))) 18 | ;; =>

x

19 | (if (atom lis) lis 20 | (let c car.lis 21 | (if (isa c 'sym) 22 | (+ "<" c ">" (string:map [simple-render _] cdr.lis) "") 23 | (isa c 'cons) 24 | (string:map [simple-render _] lis))))) 25 | 26 | (def mappendtable (f tbl) 27 | (let l (coerce tbl 'cons) 28 | (mappend [f car._ cadr._] l))) 29 | 30 | (defgeneric table-to-html (obj) (string obj)) 31 | (defmethod table-to-html (obj) cons 32 | `(li ,@(map1 (fn (i) `(li ,(table-to-html i))) obj))) 33 | (defmethod table-to-html (obj) table 34 | `(dl ,@(mappendtable (fn (k v) `((dt ,k) (dd ,(table-to-html v)))) obj))) 35 | 36 | (mac defpage (method path reqs . body) 37 | `(sref *url* 38 | (fn ,reqs (simple-render (do ,@body))) ;; this is demo, reqs is simply ignored. 39 | (list ',method ,(string path)))) 40 | 41 | (defpage GET /index (data headers) 42 | `(html 43 | (body 44 | (h1 ,"hello this is index-page.") 45 | (p ,(+ "now is " (arc.time::msec)))))) 46 | 47 | (let times 0 48 | (defpage GET /page1 (data headers) 49 | `(html 50 | (body 51 | (h1 ,"this is page1") 52 | (p ,(+ "You've accessed this page " (++ times) " times")))))) 53 | -------------------------------------------------------------------------------- /demo/web_server.js: -------------------------------------------------------------------------------- 1 | /* require "express", "shelljs", "body-parser", "underscore" */ 2 | 3 | var express = require('express'); 4 | var app = express(); 5 | var shell = require('shelljs'); 6 | var bodyParser = require('body-parser'); 7 | var _ = require('underscore'); 8 | 9 | var ArcJS = require('./arc.js'); 10 | var arc = ArcJS.context(); 11 | 12 | var json_to_arctbl = function(d) { 13 | if ( d instanceof Array) { 14 | return "(list " + d.map(json_to_arctbl).join(' ') + ")"; 15 | } else if ( d instanceof Object ) { 16 | var tmp = [], i = 0; 17 | for (var k in d) { 18 | tmp[i] = (ArcJS.stringify(k) + ' ' + json_to_arctbl(d[k])); 19 | i++; 20 | } 21 | return "{" + tmp.join(' ') + "}"; 22 | } else if (d === false || d === null) { 23 | return "nil"; 24 | } else if (d === true) { 25 | return "t"; 26 | } else { 27 | return ArcJS.stringify(d); 28 | } 29 | throw new Error('Invalid json'); 30 | }; 31 | 32 | var create_arc_method_func = function(method) { 33 | return function(request, response) { 34 | 35 | var path = '/' + request.params[0]; 36 | var query = request.query; 37 | var body = request.body; 38 | var data = _.extend(query, body); 39 | var headers = request.headers; 40 | 41 | console.log('----------------------------------------'); 42 | console.log('path: ' + method + ' ' + path); 43 | console.log('data: ' + JSON.stringify(data)); 44 | console.log('head: ' + JSON.stringify(headers)); 45 | console.log(''); 46 | 47 | try { 48 | var arc_code = '(exec-url "' + path + '" \'' + method + ' ' + json_to_arctbl(data) + ' ' + json_to_arctbl(headers) + ')'; 49 | var arc_alist = arc.evaluate(arc_code, 'user.server'); 50 | var res = {}; 51 | ArcJS.list_to_javascript_arr(arc_alist, true).forEach(function(itm) { 52 | res[itm[0]] = itm[1]; 53 | }); 54 | var code = res["code"]; 55 | var body = res["body"]; 56 | delete res["code"]; 57 | delete res["body"]; 58 | response.status(code).set(res).send(body).end(); 59 | } catch (err) { 60 | err = '500: Internal server error.\n' + err + '\n'; 61 | response.status(500).set({"Content-Type": "text/plain"}).send(err).end(); 62 | } 63 | }; 64 | }; 65 | 66 | app.use(bodyParser.urlencoded({ extended: false })); 67 | app.use(bodyParser.json()); 68 | 69 | app.get('/*', create_arc_method_func('GET')); 70 | app.post('/*', create_arc_method_func('POST')); 71 | app.put('/*', create_arc_method_func('PUT')); 72 | app.delete('/*', create_arc_method_func('DELETE')); 73 | 74 | arc.require(['web_defs.arc'], function onload() { 75 | 76 | ArcJS.Primitives('user.server').define({ 77 | 'exec-command': [{dot: -1}, function(cmd) { 78 | var rt = shell.exec(cmd); 79 | return ArcJS.Table().load_from_js_hash(rt); 80 | }] 81 | }); 82 | 83 | var port = 8090; 84 | app.listen(port); 85 | console.log("Server running at http://localhost:" + port ); 86 | 87 | }); 88 | 89 | 90 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ArcJS.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ArcJS.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/ArcJS" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ArcJS" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | virtualenv --python=python2.7 env 2 | source env/bin/arctivate 3 | pip install -r requirements.txt 4 | make html -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==2.10.1 2 | MarkupSafe==0.23 3 | Pygments==1.6 4 | Sphinx==1.2.2 5 | docutils==0.12 6 | sphinx-rtd-theme==0.1.6 7 | wsgiref==0.1.2 8 | -------------------------------------------------------------------------------- /docs/source/_static/arc_loader.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | var runner = ArcJS.context(); 3 | var codes = $('script[type="text/arc"]').map(function(i, v) { 4 | var inner = v.innerText; 5 | var src = v.src; 6 | return {script: inner, src: src}; 7 | }); 8 | var fasls = $('script[type="text/arc-fasl"]').map(function(i, v) { 9 | var inner = v.innerText; 10 | var src = v.src; 11 | return {script: inner, src: src}; 12 | }); 13 | 14 | function iter(codes, i, type, after) { 15 | if (i < codes.length) { 16 | var script = codes[i].script 17 | var src = codes[i].src; 18 | if (src) { 19 | $.ajax({ 20 | url: src, 21 | dataType: 'text' 22 | }).done(function(data){ 23 | var fasl; 24 | switch(type) { 25 | case 'fasl': 26 | eval('var fasl = (function() {\nvar preloads = [], preload_vals = [];\n' + 27 | data + 28 | 'return {preloads: preloads, preload_vals: preload_vals};\n})();'); 29 | ArcJS.fasl_loader(ArcJS.NameSpace.get('user'), fasl.preloads, fasl.preload_vals); 30 | break; 31 | case 'arc': 32 | runner.evaluate(data); 33 | break; 34 | } 35 | if (script) runner.evaluate(script); 36 | iter(codes, i+1, type, after); 37 | }); 38 | } else { 39 | if (script) runner.evaluate(script); 40 | iter(codes, i+1, type, after); 41 | } 42 | } else { 43 | if (after) after(); 44 | } 45 | } 46 | 47 | iter(fasls, 0, 'fasl', function() { 48 | iter(codes, 0, 'arc'); 49 | }); 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /docs/source/_static/avg.js.fasl: -------------------------------------------------------------------------------- 1 | // This is an auto generated file. 2 | // Compiled from ['avg.arc']. 3 | // DON'T EDIT !!! 4 | preloads.push([ 5 | [12,7,14,20,0,1,0,20,2,-1,0,10,9,1,7,9,0,7,6,0,7,11,1,21,22,7,6,0,7,6,0,7,11,2,21,5,3,3,22,16,0,0,0,11,8,0,0,21,7,6,3,7,6,0,7,11,4,21,22,8,0,0,21,15,2,2,19,3,26], 6 | ]); 7 | preload_vals.push(["2","+","/","average","fn-name"]); 8 | -------------------------------------------------------------------------------- /docs/source/_static/fasl_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/source/_static/fizzbuzz.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 21 | 22 | 23 | 24 | 25 | 38 | 39 | -------------------------------------------------------------------------------- /docs/source/_static/hw.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 23 | 24 | -------------------------------------------------------------------------------- /docs/source/_static/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var canvas = document.getElementById('c1'); 4 | var ctx = canvas.getContext('2d'); 5 | var board_size = 600; 6 | var unit = board_size / 8.0; 7 | 8 | (new ArcJS.Primitives('user')).define({ 9 | 'js/clear-board': [{dot: -1}, function clear_board() { 10 | ctx.fillStyle = "#007F4C"; 11 | ctx.fillRect(0, 0, board_size, board_size); 12 | for (var i = 0; i < 2; i++) { 13 | for (var j = 1; j < 8; j++) { 14 | var p = j * unit, s = board_size; 15 | ctx.beginPath(); 16 | ctx.moveTo(i?0:p, i?p:0); 17 | ctx.lineTo(i?s:p, i?p:s); 18 | ctx.strokeStyle = "#000000"; 19 | ctx.lineWidth = 1; 20 | ctx.closePath(); 21 | ctx.stroke(); 22 | } 23 | } 24 | }], 25 | 'js/draw-stone': [{dot: -1}, function draw_xy(x, y, color) { 26 | var hu = (unit / 2.0); 27 | var cx = (x * unit) + hu, cy = (y * unit) + hu, r = hu * 0.8; 28 | ctx.beginPath(); 29 | ctx.arc(cx, cy, r, 0, 2*Math.PI, false); 30 | ctx.fillStyle = color; 31 | ctx.fill(); 32 | ctx.lineWidth = 1; 33 | ctx.strokeStyle = "#000000"; 34 | ctx.stroke(); 35 | }] 36 | }); 37 | 38 | function getMousePos(evt) { 39 | var rect = canvas.getBoundingClientRect(); 40 | return { 41 | x: evt.clientX - rect.left, 42 | y: evt.clientY - rect.top 43 | }; 44 | } 45 | 46 | canvas.addEventListener('mousedown', function(evt) { 47 | var pos = getMousePos(evt); 48 | console.log("x: " + (pos.x|0) + " y: " + (pos.y|0)); 49 | }, false); 50 | 51 | })(); 52 | -------------------------------------------------------------------------------- /docs/source/_static/reversi.arc: -------------------------------------------------------------------------------- 1 | (import "arc.time") 2 | 3 | (= ev-depth 3) ;; depth of searching 4 | (= ev-space 10) ;; space of searching 5 | 6 | (mac keying (x y) 7 | `(+ ,x "-" ,y)) 8 | 9 | (mac unkeying (key) 10 | (w/uniq key-s 11 | `(let ,key-s ,key 12 | (cons (int:string (,key-s 0)) 13 | (int:string (,key-s 2)))))) 14 | 15 | (mac invert (color) 16 | `(if (is ,color 'w) 'b 'w)) 17 | 18 | (mac getxy (k board) `(,board ,k)) 19 | 20 | (def setxy (k board color (o copy? t)) 21 | (let rt (if copy? (copy board) board) 22 | (= (rt k) color))) 23 | 24 | (def setxy-multiple (k-list board color (o copy? t)) 25 | (let rt (if copy? (copy board) board) 26 | ((afn (ks) 27 | (if ks 28 | (do 29 | (setxy (car ks) rt color nil) 30 | (self (cdr ks))) 31 | rt)) 32 | k-list))) 33 | 34 | (def list-to-table (lis) 35 | (with (rt {} x 0 y 0) 36 | (map (fn (l) 37 | (map (fn (c) 38 | (= (rt (keying x y)) c) 39 | (++ x)) 40 | l) 41 | (= x 0) 42 | (++ y)) 43 | lis) 44 | rt)) 45 | 46 | (= ev-tbl 47 | (list-to-table 48 | '((400 -2 4 0 0 4 -2 400) 49 | ( -2 -50 0 0 0 0 -50 -2) 50 | ( 4 0 4 0 0 4 0 4) 51 | ( 0 0 0 0 0 0 0 0) 52 | ( 0 0 0 0 0 0 0 0) 53 | ( 4 0 4 0 0 4 0 4) 54 | ( -2 -50 0 0 0 0 -50 -2) 55 | (400 -2 4 0 0 4 -2 400)))) 56 | 57 | (= positions-all 58 | (map (fn (x) 59 | (map (fn (y) (keying x y)) 60 | (range 0 7))) 61 | (range 0 7))) 62 | 63 | (def get-around-position-1 (k n) 64 | (with (fs (list [- _ n] idfn [+ _ n]) 65 | (x . y) (unkeying k)) 66 | (rem 67 | k 68 | (mappend 69 | (fn (f1) 70 | (map 71 | (fn (f2) 72 | (with (x (f1 x) y (f2 y)) 73 | (if (and (< -1 x 8) (< -1 y 8)) 74 | (keying x y)))) 75 | fs)) 76 | fs)))) 77 | 78 | (let memo {} 79 | (def get-around-positions (k) 80 | (aif (memo k) 81 | it 82 | (ret rt 83 | (rem nil 84 | (apply map 85 | (compose [rem nil _] list) 86 | (map (fn (n) (get-around-position-1 k n)) (range 1 7)))) 87 | (= (memo k) rt))))) 88 | 89 | (mac collect-around-positions (k board . options) 90 | (w/uniq (board-s) 91 | `(with (,board-s ,board) 92 | (mappend 93 | (fn (ks) 94 | ((afn (ks acc) 95 | (if ks 96 | (let pos-color (getxy (car ks) ,board-s) 97 | (if ,@(mappend 98 | (fn (opt) 99 | `((is pos-color ,(car opt)) 100 | ,(case (cadr opt) 101 | next `(self (cdr ks) (cons (car ks) acc)) 102 | return `(if acc (list (car ks))) 103 | return-collecting `(nrev acc)))) 104 | (pair options)))))) 105 | ks nil)) 106 | (get-around-positions ,k))))) 107 | 108 | (def get-possible-around-positions (k board color) 109 | (collect-around-positions 110 | k board 111 | (invert color) next 112 | color return-collecting)) 113 | 114 | (def get-puttable-around-positions (k board color) 115 | (collect-around-positions 116 | k board 117 | (invert color) next 118 | 'e return)) 119 | 120 | (mac can-put? (k board color) 121 | (w/uniq (k-s board-s) 122 | `(with (,k-s ,k ,board-s ,board) 123 | (and (is (getxy ,k-s ,board-s) 'e) 124 | (get-possible-around-positions ,k-s ,board-s ,color))))) 125 | 126 | (def get-all-positions-of-color (board color) 127 | (mappend 128 | (fn (l) 129 | (mappend 130 | (fn (k) 131 | (if (is (getxy k board) color) 132 | (cons k nil))) 133 | l)) 134 | positions-all)) 135 | 136 | (def get-puttable-positions-all (board color) 137 | (let all-starts (get-all-positions-of-color board color) 138 | (dedup (mappend [get-puttable-around-positions _ board color] all-starts)))) 139 | 140 | (def put (k board color (o copy? t)) 141 | (setxy-multiple 142 | (cons k (get-possible-around-positions k board color)) 143 | board 144 | color 145 | copy?)) 146 | 147 | (def get-points (board color) 148 | (let all-starts (get-all-positions-of-color board color) 149 | (apply + (map ev-tbl all-starts)))) 150 | 151 | (def get-rand (l n) 152 | (if (> n 0) 153 | (if (>= n (len l)) 154 | l 155 | (let x (rand-elt l) 156 | (cons x 157 | (get-rand (rem x l) (- n 1))))))) 158 | 159 | (def has-empty? (board) 160 | (find 'e (map cadr (coerce board 'cons)))) 161 | 162 | (def get-best (board color depth) 163 | ((afn (board color depth target-color alpha beta) 164 | (if (or (is depth 0) 165 | (no (has-empty? board))) ;; last-depth or game-set 166 | (list (get-points board target-color)) 167 | (withs (my-turn (is target-color color) 168 | best-con (if my-turn > <) 169 | best-fn (fn (a b) (best-con (car a) (car b))) 170 | invert-color (invert color)) 171 | (iflet 172 | puttable (get-puttable-positions-all board color) 173 | 174 | (ccc 175 | (fn (return) 176 | (best 177 | best-fn 178 | (map 179 | (fn (vp) 180 | (let new-board (put vp board color) 181 | (ret point-move (self new-board invert-color (- depth 1) target-color alpha beta) 182 | (let point (car point-move) 183 | (if my-turn 184 | (when (> point alpha) 185 | (= alpha point) 186 | (if (>= alpha beta) 187 | (return (cons beta vp)))) ;; alpha-cut 188 | (when (< point beta) 189 | (= beta point) 190 | (if (>= alpha beta) 191 | (return (cons alpha vp)))))) ;; beta-cut 192 | (scdr point-move vp)))) 193 | (get-rand puttable ev-space))))) ;; cut-off if candidates are over space. 194 | 195 | (self board invert-color (- depth 1) target-color alpha beta))))) ;; pass 196 | 197 | board color depth color -inf.0 +inf.0)) 198 | 199 | (def count-color (board color) 200 | (len (get-all-positions-of-color board color))) 201 | 202 | (def print-board (board) 203 | (for y 0 7 204 | (let str "" 205 | (for x 0 7 206 | (= str (+ str (case (board (keying x y)) 207 | e "--" 208 | w "WW" 209 | b "BB")))) 210 | (js/log str))) 211 | (js/log "")) 212 | 213 | (def make-new-board () 214 | (list-to-table (n-of 8 (n-of 8 'e)))) 215 | 216 | (def init-board () 217 | (let board (make-new-board) 218 | (setxy-multiple '("3-4" "4-3") board 'b nil) 219 | (setxy-multiple '("3-3" "4-4") board 'w nil))) 220 | 221 | (def game () 222 | (with (board (init-board) 223 | turn 'b 224 | n 0) 225 | 226 | (js/log "\n\n\n\n\n\n *** NEW GAME START *** \n\n") 227 | 228 | (while 229 | (has-empty? board) 230 | (print-board board) 231 | (js/log "") 232 | (js/log "TURN " n ": " (if (is turn 'b) "BLACK" "WHITE")) 233 | (js/log "POINT: " (get-points board turn)) 234 | (let pos (cdr (get-best board turn ev-depth)) 235 | (if pos 236 | (do 237 | (pr "PUT: " pos "\n") 238 | (put pos board turn nil)) 239 | board)) 240 | (= turn (invert turn)) 241 | (++ n) 242 | (js/log "")) 243 | 244 | (with (wnum (count-color board 'w) 245 | bnum (count-color board 'b)) 246 | (js/log "WHITE: " wnum) 247 | (js/log "BLACK: " bnum "\n\n") 248 | (js/log (if (> wnum bnum) 249 | " !!! WHITE won !!!\n\n" 250 | (> bnum wnum) 251 | " !!! BLACK won !!!\n\n" 252 | " !!! DRAW !!!\n\n"))))) 253 | 254 | (def draw-board (board) 255 | (js/clear-board) 256 | (for y 0 7 257 | (for x 0 7 258 | (case (board (keying x y)) 259 | w (js/draw-stone x y "white") 260 | b (js/draw-stone x y "black") 261 | e "Noting to do")))) 262 | 263 | (def turn1 (board turn n) 264 | (if (has-empty? board) 265 | (do1 266 | t 267 | (js/log "TURN " n ": " (if (is turn 'b) "BLACK" "WHITE")) 268 | (js/log "POINT: " (get-points board turn)) 269 | (js/log "Searching... ") 270 | (let pos (cdr (get-best board turn ev-depth)) 271 | (if pos 272 | (do 273 | (js/log "PUT: " pos) 274 | (put pos board turn nil) 275 | (draw-board board) 276 | (print-board board)) 277 | board))))) 278 | 279 | (def start-game () 280 | (with (board (init-board) 281 | turn 'b 282 | n 0) 283 | 284 | (js/log "\n\n\n\n\n\n *** NEW GAME START *** \n") 285 | 286 | (def game-set () 287 | (with (wnum (count-color board 'w) 288 | bnum (count-color board 'b)) 289 | (js/log "WHITE: " wnum) 290 | (js/log "BLACK: " bnum "\n\n") 291 | (js/log (if (> wnum bnum) 292 | " !!! WHITE won !!!\n\n" 293 | (> bnum wnum) 294 | " !!! BLACK won !!!\n\n" 295 | " !!! DRAW !!!\n\n")))) 296 | 297 | (def iter () 298 | (if (turn1 board turn n) 299 | (do 300 | (= turn (invert turn)) 301 | (++ n) 302 | (js/log "") 303 | (set-timer iter 10)) 304 | (game-set))) 305 | 306 | (print-board board) 307 | 308 | (iter))) -------------------------------------------------------------------------------- /docs/source/_static/reversi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reversi 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Reversi

12 | 13 | 14 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/source/_static/reversi_bridge.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var canvas = document.getElementById('c1'); 3 | var size = 600; 4 | var txt = '', holder = $('#holder'); 5 | 6 | function clear_board() { 7 | var ctx = canvas.getContext('2d'); 8 | ctx.fillStyle = "rgb(0, 153, 0)"; 9 | ctx.fillRect(0, 0, size, size); 10 | var unit = size / 8; 11 | for (var i = 1, l = 8; i v documentation". 128 | #html_title = None 129 | 130 | # A shorter title for the navigation bar. Default is the same as html_title. 131 | #html_short_title = None 132 | 133 | # The name of an image file (relative to this directory) to place at the top 134 | # of the sidebar. 135 | #html_logo = None 136 | 137 | # The name of an image file (within the static path) to use as favicon of the 138 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 139 | # pixels large. 140 | #html_favicon = None 141 | 142 | # Add any paths that contain custom static files (such as style sheets) here, 143 | # relative to this directory. They are copied after the builtin static files, 144 | # so a file named "default.css" will overwrite the builtin "default.css". 145 | html_static_path = ['_static'] 146 | 147 | # Add any extra paths that contain custom files (such as robots.txt or 148 | # .htaccess) here, relative to this directory. These files are copied 149 | # directly to the root of the documentation. 150 | #html_extra_path = [] 151 | 152 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 153 | # using the given strftime format. 154 | #html_last_updated_fmt = '%b %d, %Y' 155 | 156 | # If true, SmartyPants will be used to convert quotes and dashes to 157 | # typographically correct entities. 158 | #html_use_smartypants = True 159 | 160 | # Custom sidebar templates, maps document names to template names. 161 | #html_sidebars = {} 162 | 163 | # Additional templates that should be rendered to pages, maps page names to 164 | # template names. 165 | #html_additional_pages = {} 166 | 167 | # If false, no module index is generated. 168 | #html_domain_indices = True 169 | 170 | # If false, no index is generated. 171 | #html_use_index = True 172 | 173 | # If true, the index is split into individual pages for each letter. 174 | #html_split_index = False 175 | 176 | # If true, links to the reST sources are added to the pages. 177 | #html_show_sourcelink = True 178 | 179 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 180 | #html_show_sphinx = True 181 | 182 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 183 | #html_show_copyright = True 184 | 185 | # If true, an OpenSearch description file will be output, and all pages will 186 | # contain a tag referring to it. The value of this option must be the 187 | # base URL from which the finished HTML is served. 188 | #html_use_opensearch = '' 189 | 190 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 191 | #html_file_suffix = None 192 | 193 | # Output file base name for HTML help builder. 194 | htmlhelp_basename = 'ArcJSdoc' 195 | 196 | 197 | # -- Options for LaTeX output --------------------------------------------- 198 | 199 | latex_elements = { 200 | # The paper size ('letterpaper' or 'a4paper'). 201 | #'papersize': 'letterpaper', 202 | 203 | # The font size ('10pt', '11pt' or '12pt'). 204 | #'pointsize': '10pt', 205 | 206 | # Additional stuff for the LaTeX preamble. 207 | #'preamble': '', 208 | } 209 | 210 | # Grouping the document tree into LaTeX files. List of tuples 211 | # (source start file, target name, title, 212 | # author, documentclass [howto, manual, or own class]). 213 | latex_documents = [ 214 | ('index', 'ArcJS.tex', u'ArcJS Documentation', 215 | u'smihica', 'manual'), 216 | ] 217 | 218 | # The name of an image file (relative to this directory) to place at the top of 219 | # the title page. 220 | #latex_logo = None 221 | 222 | # For "manual" documents, if this is true, then toplevel headings are parts, 223 | # not chapters. 224 | #latex_use_parts = False 225 | 226 | # If true, show page references after internal links. 227 | #latex_show_pagerefs = False 228 | 229 | # If true, show URL addresses after external links. 230 | #latex_show_urls = False 231 | 232 | # Documents to append as an appendix to all manuals. 233 | #latex_appendices = [] 234 | 235 | # If false, no module index is generated. 236 | #latex_domain_indices = True 237 | 238 | 239 | # -- Options for manual page output --------------------------------------- 240 | 241 | # One entry per manual page. List of tuples 242 | # (source start file, name, description, authors, manual section). 243 | man_pages = [ 244 | ('index', 'arcjs', u'ArcJS Documentation', 245 | [u'smihica'], 1) 246 | ] 247 | 248 | # If true, show URL addresses after external links. 249 | #man_show_urls = False 250 | 251 | 252 | # -- Options for Texinfo output ------------------------------------------- 253 | 254 | # Grouping the document tree into Texinfo files. List of tuples 255 | # (source start file, target name, title, author, 256 | # dir menu entry, description, category) 257 | texinfo_documents = [ 258 | ('index', 'ArcJS', u'ArcJS Documentation', 259 | u'smihica', 'ArcJS', 'One line description of project.', 260 | 'Miscellaneous'), 261 | ] 262 | 263 | # Documents to append as an appendix to all manuals. 264 | #texinfo_appendices = [] 265 | 266 | # If false, no module index is generated. 267 | #texinfo_domain_indices = True 268 | 269 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 270 | #texinfo_show_urls = 'footnote' 271 | 272 | # If true, do not generate a @detailmenu in the "Top" node's menu. 273 | #texinfo_no_detailmenu = False 274 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. ArcJS documentation master file, created by 2 | sphinx-quickstart on Fri Jul 18 13:19:07 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ArcJS - 0.1.x documentation 7 | =========================== 8 | 9 | Contents 10 | ^^^^^^^^ 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | 15 | tutorial 16 | refs 17 | 18 | What is ArcJS? 19 | ^^^^^^^^^^^^^^ 20 | 21 | ArcJS is an Arc-language implementation written in JavaScript. 22 | It consists of a self-hosting compiler written in Arc and a StackVM written in JavaScript. 23 | 24 | **Main features** 25 | 26 | * It runs on its StackVM [#f1]_ so the Arc-code is compiled into asm-code in advance for performance. 27 | * The Arc compiler is written in Arc itself. (Self-hosting compiler) [#f2]_ 28 | * macros, objects, first-class continuations and tail-call optimization are completely supported. 29 | * Arc's characteristic features; default function, ssyntax are also supported. 30 | 31 | **ArcJS's original features (Not in official Arc-language)** 32 | 33 | * User defined ssyntax. 34 | * clojure-like namepace system. 35 | * new syntax (table, etc) 36 | * stack tracer. (debuger) 37 | 38 | .. [#f1] `vm.js `_ 39 | .. [#f2] `compiler.arc `_ 40 | 41 | What is Arc-language? 42 | ^^^^^^^^^^^^^^^^^^^^^ 43 | 44 | Arc-language is a dialect of the Lisp programming language now under development by Paul Graham and Robert Morris. 45 | Its simpler than Common-Lisp and more powerful than Scheme (IMO). [#f3]_ 46 | 47 | .. [#f3] `Official Home Page `_ 48 | -------------------------------------------------------------------------------- /docs/source/refs.rst: -------------------------------------------------------------------------------- 1 | ******************* 2 | NameSpace reference 3 | ******************* 4 | 5 | **NOW WORK IN PROGRESS** 6 | 7 | arc.core 8 | ======== 9 | 10 | core utils for arc. 11 | 12 | arc.arc 13 | ======= 14 | 15 | arc's main functions. 16 | 17 | arc.collection 18 | ============== 19 | 20 | function set for collection. 21 | 22 | arc.compiler 23 | ============ 24 | 25 | arc compiler functions. 26 | 27 | arc.unit 28 | ======== 29 | 30 | for unit testing. 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /lib/classify.js: -------------------------------------------------------------------------------- 1 | var classify = (function(ns) { 2 | 3 | var classify = ns; 4 | 5 | function randomAscii(len) { 6 | for(var rt='';0", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; 8 | function findMatchingBracket(cm) { 9 | var maxScanLen = cm.state._matchBrackets.maxScanLineLength || 10000; 10 | 11 | var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1; 12 | var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; 13 | if (!match) return null; 14 | var forward = match.charAt(1) == ">", d = forward ? 1 : -1; 15 | var style = cm.getTokenAt(Pos(cur.line, pos + 1)).type; 16 | 17 | var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; 18 | function scan(line, lineNo, start) { 19 | if (!line.text) return; 20 | var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1; 21 | if (line.text.length > maxScanLen) return null; 22 | var checkTokenStyles = line.text.length < 1000; 23 | if (start != null) pos = start + d; 24 | for (; pos != end; pos += d) { 25 | var ch = line.text.charAt(pos); 26 | if (re.test(ch) && (!checkTokenStyles || cm.getTokenAt(Pos(lineNo, pos + 1)).type == style)) { 27 | var match = matching[ch]; 28 | if (match.charAt(1) == ">" == forward) stack.push(ch); 29 | else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; 30 | else if (!stack.length) return {pos: pos, match: true}; 31 | } 32 | } 33 | } 34 | for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) { 35 | if (i == cur.line) found = scan(line, i, pos); 36 | else found = scan(cm.getLineHandle(i), i); 37 | if (found) break; 38 | } 39 | return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos), match: found && found.match}; 40 | } 41 | 42 | function matchBrackets(cm, autoclear) { 43 | // Disable brace matching in long lines, since it'll cause hugely slow updates 44 | var maxHighlightLen = cm.state._matchBrackets.maxHighlightLineLength || 1000; 45 | var found = findMatchingBracket(cm); 46 | if (!found || cm.getLine(found.from.line).length > maxHighlightLen || 47 | found.to && cm.getLine(found.to.line).length > maxHighlightLen) 48 | return; 49 | 50 | var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; 51 | var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style}); 52 | var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style}); 53 | // Kludge to work around the IE bug from issue #1193, where text 54 | // input stops going to the textare whever this fires. 55 | if (ie_lt8 && cm.state.focused) cm.display.input.focus(); 56 | var clear = function() { 57 | cm.operation(function() { one.clear(); two && two.clear(); }); 58 | }; 59 | if (autoclear) setTimeout(clear, 800); 60 | else return clear; 61 | } 62 | 63 | var currentlyHighlighted = null; 64 | function doMatchBrackets(cm) { 65 | cm.operation(function() { 66 | if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} 67 | if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false); 68 | }); 69 | } 70 | 71 | CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { 72 | if (old && old != CodeMirror.Init) 73 | cm.off("cursorActivity", doMatchBrackets); 74 | if (val) { 75 | cm.state._matchBrackets = typeof val == "object" ? val : {}; 76 | cm.on("cursorActivity", doMatchBrackets); 77 | } 78 | }); 79 | 80 | CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); 81 | CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);}); 82 | })(); 83 | -------------------------------------------------------------------------------- /lib/codemirror/lib/codemirror.css: -------------------------------------------------------------------------------- 1 | /* BASICS */ 2 | 3 | .CodeMirror { 4 | /* Set height, width, borders, and global font properties here */ 5 | font-family: monospace; 6 | height: 300px; 7 | } 8 | .CodeMirror-scroll { 9 | /* Set scrolling behaviour here */ 10 | overflow: auto; 11 | } 12 | 13 | /* PADDING */ 14 | 15 | .CodeMirror-lines { 16 | padding: 4px 0; /* Vertical padding around content */ 17 | } 18 | .CodeMirror pre { 19 | padding: 0 4px; /* Horizontal padding of content */ 20 | } 21 | 22 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 23 | background-color: white; /* The little square between H and V scrollbars */ 24 | } 25 | 26 | /* GUTTER */ 27 | 28 | .CodeMirror-gutters { 29 | border-right: 1px solid #ddd; 30 | background-color: #f7f7f7; 31 | white-space: nowrap; 32 | } 33 | .CodeMirror-linenumbers {} 34 | .CodeMirror-linenumber { 35 | padding: 0 3px 0 5px; 36 | min-width: 20px; 37 | text-align: right; 38 | color: #999; 39 | } 40 | 41 | /* CURSOR */ 42 | 43 | .CodeMirror div.CodeMirror-cursor { 44 | border-left: 1px solid black; 45 | z-index: 3; 46 | } 47 | /* Shown when moving in bi-directional text */ 48 | .CodeMirror div.CodeMirror-secondarycursor { 49 | border-left: 1px solid silver; 50 | } 51 | .CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { 52 | width: auto; 53 | border: 0; 54 | background: #7e7; 55 | z-index: 1; 56 | } 57 | /* Can style cursor different in overwrite (non-insert) mode */ 58 | .CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} 59 | 60 | .cm-tab { display: inline-block; } 61 | 62 | /* DEFAULT THEME */ 63 | 64 | .cm-s-default .cm-keyword {color: #708;} 65 | .cm-s-default .cm-atom {color: #219;} 66 | .cm-s-default .cm-number {color: #164;} 67 | .cm-s-default .cm-def {color: #00f;} 68 | .cm-s-default .cm-variable {color: black;} 69 | .cm-s-default .cm-variable-2 {color: #05a;} 70 | .cm-s-default .cm-variable-3 {color: #085;} 71 | .cm-s-default .cm-property {color: black;} 72 | .cm-s-default .cm-operator {color: black;} 73 | .cm-s-default .cm-comment {color: #a50;} 74 | .cm-s-default .cm-string {color: #a11;} 75 | .cm-s-default .cm-string-2 {color: #f50;} 76 | .cm-s-default .cm-meta {color: #555;} 77 | .cm-s-default .cm-error {color: #f00;} 78 | .cm-s-default .cm-qualifier {color: #555;} 79 | .cm-s-default .cm-builtin {color: #30a;} 80 | .cm-s-default .cm-bracket {color: #997;} 81 | .cm-s-default .cm-tag {color: #170;} 82 | .cm-s-default .cm-attribute {color: #00c;} 83 | .cm-s-default .cm-header {color: blue;} 84 | .cm-s-default .cm-quote {color: #090;} 85 | .cm-s-default .cm-hr {color: #999;} 86 | .cm-s-default .cm-link {color: #00c;} 87 | 88 | .cm-negative {color: #d44;} 89 | .cm-positive {color: #292;} 90 | .cm-header, .cm-strong {font-weight: bold;} 91 | .cm-em {font-style: italic;} 92 | .cm-link {text-decoration: underline;} 93 | 94 | .cm-invalidchar {color: #f00;} 95 | 96 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 97 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 98 | 99 | /* STOP */ 100 | 101 | /* The rest of this file contains styles related to the mechanics of 102 | the editor. You probably shouldn't touch them. */ 103 | 104 | .CodeMirror { 105 | line-height: 1; 106 | position: relative; 107 | overflow: hidden; 108 | background: white; 109 | color: black; 110 | } 111 | 112 | .CodeMirror-scroll { 113 | /* 30px is the magic margin used to hide the element's real scrollbars */ 114 | /* See overflow: hidden in .CodeMirror */ 115 | margin-bottom: -30px; margin-right: -30px; 116 | padding-bottom: 30px; padding-right: 30px; 117 | height: 100%; 118 | outline: none; /* Prevent dragging from highlighting the element */ 119 | position: relative; 120 | } 121 | .CodeMirror-sizer { 122 | position: relative; 123 | } 124 | 125 | /* The fake, visible scrollbars. Used to force redraw during scrolling 126 | before actuall scrolling happens, thus preventing shaking and 127 | flickering artifacts. */ 128 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 129 | position: absolute; 130 | z-index: 6; 131 | display: none; 132 | } 133 | .CodeMirror-vscrollbar { 134 | right: 0; top: 0; 135 | overflow-x: hidden; 136 | overflow-y: scroll; 137 | } 138 | .CodeMirror-hscrollbar { 139 | bottom: 0; left: 0; 140 | overflow-y: hidden; 141 | overflow-x: scroll; 142 | } 143 | .CodeMirror-scrollbar-filler { 144 | right: 0; bottom: 0; 145 | } 146 | .CodeMirror-gutter-filler { 147 | left: 0; bottom: 0; 148 | } 149 | 150 | .CodeMirror-gutters { 151 | position: absolute; left: 0; top: 0; 152 | padding-bottom: 30px; 153 | z-index: 3; 154 | } 155 | .CodeMirror-gutter { 156 | white-space: normal; 157 | height: 100%; 158 | padding-bottom: 30px; 159 | margin-bottom: -32px; 160 | display: inline-block; 161 | /* Hack to make IE7 behave */ 162 | *zoom:1; 163 | *display:inline; 164 | } 165 | .CodeMirror-gutter-elt { 166 | position: absolute; 167 | cursor: default; 168 | z-index: 4; 169 | } 170 | 171 | .CodeMirror-lines { 172 | cursor: text; 173 | } 174 | .CodeMirror pre { 175 | /* Reset some styles that the rest of the page might have set */ 176 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 177 | border-width: 0; 178 | background: transparent; 179 | font-family: inherit; 180 | font-size: inherit; 181 | margin: 0; 182 | white-space: pre; 183 | word-wrap: normal; 184 | line-height: inherit; 185 | color: inherit; 186 | z-index: 2; 187 | position: relative; 188 | overflow: visible; 189 | } 190 | .CodeMirror-wrap pre { 191 | word-wrap: break-word; 192 | white-space: pre-wrap; 193 | word-break: normal; 194 | } 195 | .CodeMirror-code pre { 196 | border-right: 30px solid transparent; 197 | width: -webkit-fit-content; 198 | width: -moz-fit-content; 199 | width: fit-content; 200 | } 201 | .CodeMirror-wrap .CodeMirror-code pre { 202 | border-right: none; 203 | width: auto; 204 | } 205 | .CodeMirror-linebackground { 206 | position: absolute; 207 | left: 0; right: 0; top: 0; bottom: 0; 208 | z-index: 0; 209 | } 210 | 211 | .CodeMirror-linewidget { 212 | position: relative; 213 | z-index: 2; 214 | overflow: auto; 215 | } 216 | 217 | .CodeMirror-widget { 218 | } 219 | 220 | .CodeMirror-wrap .CodeMirror-scroll { 221 | overflow-x: hidden; 222 | } 223 | 224 | .CodeMirror-measure { 225 | position: absolute; 226 | width: 100%; height: 0px; 227 | overflow: hidden; 228 | visibility: hidden; 229 | } 230 | .CodeMirror-measure pre { position: static; } 231 | 232 | .CodeMirror div.CodeMirror-cursor { 233 | position: absolute; 234 | visibility: hidden; 235 | border-right: none; 236 | width: 0; 237 | } 238 | .CodeMirror-focused div.CodeMirror-cursor { 239 | visibility: visible; 240 | } 241 | 242 | .CodeMirror-selected { background: #d9d9d9; } 243 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 244 | 245 | .cm-searching { 246 | background: #ffa; 247 | background: rgba(255, 255, 0, .4); 248 | } 249 | 250 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */ 251 | .CodeMirror span { *vertical-align: text-bottom; } 252 | 253 | @media print { 254 | /* Hide the cursor when printing */ 255 | .CodeMirror div.CodeMirror-cursor { 256 | visibility: hidden; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /lib/jasmine-1.3.1/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 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. 21 | -------------------------------------------------------------------------------- /lib/jasmine-1.3.1/jasmine.css: -------------------------------------------------------------------------------- 1 | body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } 2 | 3 | #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } 4 | #HTMLReporter a { text-decoration: none; } 5 | #HTMLReporter a:hover { text-decoration: underline; } 6 | #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } 7 | #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } 8 | #HTMLReporter #jasmine_content { position: fixed; right: 100%; } 9 | #HTMLReporter .version { color: #aaaaaa; } 10 | #HTMLReporter .banner { margin-top: 14px; } 11 | #HTMLReporter .duration { color: #aaaaaa; float: right; } 12 | #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } 13 | #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } 14 | #HTMLReporter .symbolSummary li.passed { font-size: 14px; } 15 | #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } 16 | #HTMLReporter .symbolSummary li.failed { line-height: 9px; } 17 | #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } 18 | #HTMLReporter .symbolSummary li.skipped { font-size: 14px; } 19 | #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } 20 | #HTMLReporter .symbolSummary li.pending { line-height: 11px; } 21 | #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } 22 | #HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; } 23 | #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 24 | #HTMLReporter .runningAlert { background-color: #666666; } 25 | #HTMLReporter .skippedAlert { background-color: #aaaaaa; } 26 | #HTMLReporter .skippedAlert:first-child { background-color: #333333; } 27 | #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } 28 | #HTMLReporter .passingAlert { background-color: #a6b779; } 29 | #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } 30 | #HTMLReporter .failingAlert { background-color: #cf867e; } 31 | #HTMLReporter .failingAlert:first-child { background-color: #b03911; } 32 | #HTMLReporter .results { margin-top: 14px; } 33 | #HTMLReporter #details { display: none; } 34 | #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } 35 | #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } 36 | #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } 37 | #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } 38 | #HTMLReporter.showDetails .summary { display: none; } 39 | #HTMLReporter.showDetails #details { display: block; } 40 | #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } 41 | #HTMLReporter .summary { margin-top: 14px; } 42 | #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } 43 | #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } 44 | #HTMLReporter .summary .specSummary.failed a { color: #b03911; } 45 | #HTMLReporter .description + .suite { margin-top: 0; } 46 | #HTMLReporter .suite { margin-top: 14px; } 47 | #HTMLReporter .suite a { color: #333333; } 48 | #HTMLReporter #details .specDetail { margin-bottom: 28px; } 49 | #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } 50 | #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } 51 | #HTMLReporter .resultMessage span.result { display: block; } 52 | #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } 53 | 54 | #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } 55 | #TrivialReporter a:visited, #TrivialReporter a { color: #303; } 56 | #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } 57 | #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } 58 | #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } 59 | #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } 60 | #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } 61 | #TrivialReporter .runner.running { background-color: yellow; } 62 | #TrivialReporter .options { text-align: right; font-size: .8em; } 63 | #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } 64 | #TrivialReporter .suite .suite { margin: 5px; } 65 | #TrivialReporter .suite.passed { background-color: #dfd; } 66 | #TrivialReporter .suite.failed { background-color: #fdd; } 67 | #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } 68 | #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } 69 | #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } 70 | #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } 71 | #TrivialReporter .spec.skipped { background-color: #bbb; } 72 | #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } 73 | #TrivialReporter .passed { background-color: #cfc; display: none; } 74 | #TrivialReporter .failed { background-color: #fbb; } 75 | #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } 76 | #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } 77 | #TrivialReporter .resultMessage .mismatch { color: black; } 78 | #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } 79 | #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } 80 | #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } 81 | #TrivialReporter #jasmine_content { position: fixed; right: 100%; } 82 | #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } 83 | -------------------------------------------------------------------------------- /lib/mocha/mocha.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | margin:0; 5 | } 6 | 7 | #mocha { 8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; 9 | margin: 60px 50px; 10 | } 11 | 12 | #mocha ul, #mocha li { 13 | margin: 0; 14 | padding: 0; 15 | } 16 | 17 | #mocha ul { 18 | list-style: none; 19 | } 20 | 21 | #mocha h1, #mocha h2 { 22 | margin: 0; 23 | } 24 | 25 | #mocha h1 { 26 | margin-top: 15px; 27 | font-size: 1em; 28 | font-weight: 200; 29 | } 30 | 31 | #mocha h1 a { 32 | text-decoration: none; 33 | color: inherit; 34 | } 35 | 36 | #mocha h1 a:hover { 37 | text-decoration: underline; 38 | } 39 | 40 | #mocha .suite .suite h1 { 41 | margin-top: 0; 42 | font-size: .8em; 43 | } 44 | 45 | #mocha .hidden { 46 | display: none; 47 | } 48 | 49 | #mocha h2 { 50 | font-size: 12px; 51 | font-weight: normal; 52 | cursor: pointer; 53 | } 54 | 55 | #mocha .suite { 56 | margin-left: 15px; 57 | } 58 | 59 | #mocha .test { 60 | margin-left: 15px; 61 | overflow: hidden; 62 | } 63 | 64 | #mocha .test.pending:hover h2::after { 65 | content: '(pending)'; 66 | font-family: arial, sans-serif; 67 | } 68 | 69 | #mocha .test.pass.medium .duration { 70 | background: #C09853; 71 | } 72 | 73 | #mocha .test.pass.slow .duration { 74 | background: #B94A48; 75 | } 76 | 77 | #mocha .test.pass::before { 78 | content: '✓'; 79 | font-size: 12px; 80 | display: block; 81 | float: left; 82 | margin-right: 5px; 83 | color: #00d6b2; 84 | } 85 | 86 | #mocha .test.pass .duration { 87 | font-size: 9px; 88 | margin-left: 5px; 89 | padding: 2px 5px; 90 | color: white; 91 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 92 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 93 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 94 | -webkit-border-radius: 5px; 95 | -moz-border-radius: 5px; 96 | -ms-border-radius: 5px; 97 | -o-border-radius: 5px; 98 | border-radius: 5px; 99 | } 100 | 101 | #mocha .test.pass.fast .duration { 102 | display: none; 103 | } 104 | 105 | #mocha .test.pending { 106 | color: #0b97c4; 107 | } 108 | 109 | #mocha .test.pending::before { 110 | content: '◦'; 111 | color: #0b97c4; 112 | } 113 | 114 | #mocha .test.fail { 115 | color: #c00; 116 | } 117 | 118 | #mocha .test.fail pre { 119 | color: black; 120 | } 121 | 122 | #mocha .test.fail::before { 123 | content: '✖'; 124 | font-size: 12px; 125 | display: block; 126 | float: left; 127 | margin-right: 5px; 128 | color: #c00; 129 | } 130 | 131 | #mocha .test pre.error { 132 | color: #c00; 133 | max-height: 300px; 134 | overflow: auto; 135 | } 136 | 137 | #mocha .test pre { 138 | display: block; 139 | float: left; 140 | clear: left; 141 | font: 12px/1.5 monaco, monospace; 142 | margin: 5px; 143 | padding: 15px; 144 | border: 1px solid #eee; 145 | border-bottom-color: #ddd; 146 | -webkit-border-radius: 3px; 147 | -webkit-box-shadow: 0 1px 3px #eee; 148 | -moz-border-radius: 3px; 149 | -moz-box-shadow: 0 1px 3px #eee; 150 | } 151 | 152 | #mocha .test h2 { 153 | position: relative; 154 | } 155 | 156 | #mocha .test a.replay { 157 | position: absolute; 158 | top: 3px; 159 | right: 0; 160 | text-decoration: none; 161 | vertical-align: middle; 162 | display: block; 163 | width: 15px; 164 | height: 15px; 165 | line-height: 15px; 166 | text-align: center; 167 | background: #eee; 168 | font-size: 15px; 169 | -moz-border-radius: 15px; 170 | border-radius: 15px; 171 | -webkit-transition: opacity 200ms; 172 | -moz-transition: opacity 200ms; 173 | transition: opacity 200ms; 174 | opacity: 0.3; 175 | color: #888; 176 | } 177 | 178 | #mocha .test:hover a.replay { 179 | opacity: 1; 180 | } 181 | 182 | #mocha-report.pass .test.fail { 183 | display: none; 184 | } 185 | 186 | #mocha-report.fail .test.pass { 187 | display: none; 188 | } 189 | 190 | #mocha-error { 191 | color: #c00; 192 | font-size: 1.5em; 193 | font-weight: 100; 194 | letter-spacing: 1px; 195 | } 196 | 197 | #mocha-stats { 198 | position: fixed; 199 | top: 15px; 200 | right: 10px; 201 | font-size: 12px; 202 | margin: 0; 203 | color: #888; 204 | z-index: 1; 205 | } 206 | 207 | #mocha-stats .progress { 208 | float: right; 209 | padding-top: 0; 210 | } 211 | 212 | #mocha-stats em { 213 | color: black; 214 | } 215 | 216 | #mocha-stats a { 217 | text-decoration: none; 218 | color: inherit; 219 | } 220 | 221 | #mocha-stats a:hover { 222 | border-bottom: 1px solid #eee; 223 | } 224 | 225 | #mocha-stats li { 226 | display: inline-block; 227 | margin: 0 5px; 228 | list-style: none; 229 | padding-top: 11px; 230 | } 231 | 232 | #mocha-stats canvas { 233 | width: 40px; 234 | height: 40px; 235 | } 236 | 237 | #mocha code .comment { color: #ddd } 238 | #mocha code .init { color: #2F6FAD } 239 | #mocha code .string { color: #5890AD } 240 | #mocha code .keyword { color: #8A6343 } 241 | #mocha code .number { color: #2F6FAD } 242 | 243 | @media screen and (max-device-width: 480px) { 244 | #mocha { 245 | margin: 60px 0px; 246 | } 247 | 248 | #mocha #stats { 249 | position: absolute; 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arc-js", 3 | "version": "0.1.5", 4 | "description": "An Arc-langugage compiler and VM-interpreter written in JavaScript.", 5 | "homepage": "http://smihica.github.io/arc-js/", 6 | "main": "arc.js", 7 | "scripts": { 8 | "test": "node_modules/mocha/bin/mocha --reporter tap test/unit/impl.js || exit 1; for tes in `ls test/unit/arc/*.arc`; do bin/arcjs $tes || exit 1; done;" 9 | }, 10 | "files": [ 11 | "arc.js", 12 | "arc.min.js", 13 | "arc_loader.js", 14 | "bin" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/smihica/arc-js.git" 19 | }, 20 | "keywords": [ 21 | "Arc", 22 | "interpreter", 23 | "language", 24 | "arclang" 25 | ], 26 | "author": "smihica", 27 | "license": "Artistic-2.0", 28 | "readmeFilename": "README.md", 29 | "bin": { 30 | "arcjs": "./bin/arcjs", 31 | "arcjsc": "./bin/arcjsc" 32 | }, 33 | "devDependencies": { 34 | "chai": "1.7.2", 35 | "mocha": "1.12.0", 36 | "uglify-js": "^3.3.23" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/arc.js: -------------------------------------------------------------------------------- 1 | var ArcJS = (function() { 2 | var ArcJS = this; 3 | 4 | ArcJS.version = '0.1.5'; 5 | #ifdef NO_EVAL 6 | ArcJS.version += ' (no-eval)'; 7 | #endif 8 | 9 | var todos_after_all_initialized = []; 10 | 11 | #ifdef NO_EVAL 12 | #include "../lib/classify.simple.js" 13 | #else 14 | #include "../lib/classify.js" 15 | #endif 16 | #include "stack.js" 17 | #include "symbol.js" 18 | #include "cons.js" 19 | #include "char.js" 20 | #include "table.js" 21 | #include "closure.js" 22 | #include "call.js" 23 | #include "continuation.js" 24 | #include "tagged.js" 25 | #include "box.js" 26 | #include "regexp.js" 27 | #include "reader.js" 28 | #include "namespace.js" 29 | #include "primitives.js" 30 | #include "preload.js" 31 | #include "vm.js" 32 | #include "context.js" 33 | 34 | for (var i = 0, l = todos_after_all_initialized.length; i" (cadr it)) 43 | (prn "") 44 | (self (+ (cddr it) 45 | `((restore ,depth ,ns ,filter)) 46 | (cdr tests)) 47 | (+ depth 1) ns filter nil nil)) 48 | test (do 49 | (let start (msec) 50 | (unless (self (cddr it) depth ns filter (cadr it) nil) 51 | (let time (- (msec) start) 52 | (++ time-all time) 53 | (++ succ-all) 54 | (log "[OK]" (cadr it) "in" time "ms")))) 55 | (++ tests-all) 56 | (let next (if (in (caadr tests) 'desc 'restore) (cons '(prn "") (cdr tests)) (cdr tests)) 57 | (set-timer self 0 nil next depth ns filter nil nil))) 58 | restore (self (cdr tests) (cadr it) (caddr it) (cadddr it) nil nil) 59 | prn (do 60 | (apply prn (cdr it)) 61 | (self (cdr tests) depth ns filter nil nil)) 62 | (err 'unknown-type))) 63 | (case it 64 | :ns (self (cddr tests) depth (cadr tests) filter in-test in-cond) 65 | :f (self (cddr tests) depth ns (cadr tests) in-test in-cond) 66 | (err (+ 'unknown-option " " it)))) 67 | (when (no (or in-test in-cond)) 68 | (let fail-all (- tests-all succ-all) 69 | (prn "** " tests-all " tests done. succ/fail => " succ-all "/" fail-all " in " time-all " ms") 70 | (when (< 0 fail-all) 71 | (err (+ fail-all " tests failed"))))))) 72 | tests 0 lex-ns idfn nil nil))) 73 | 0)) 74 | 75 | (def expand-desc (d) 76 | (list 77 | 'quasiquote 78 | (list (+ (list 'desc (car d)) 79 | ((afn (d cond acc) 80 | (if (no d) 81 | (nrev acc) 82 | (if (is (car d) :f) 83 | (self (cddr d) cond (cons (list 'unquote (cadr d)) (cons :f acc))) 84 | cond 85 | (self (cddr d) cond (cons (cadr d) (cons (car d) acc))) 86 | (acons (car d)) 87 | (let it (car d) 88 | (if (in (car it) 'is 'iso 'isnt 'isont 'do) 89 | (self (cdr d) 90 | nil 91 | (cons 92 | (+ (if (is (car it) 'do) 93 | (list unit-do) 94 | (list (eval (car it) (***lex-ns***)))) 95 | (self (cdr it) t nil)) 96 | acc)) 97 | (self (cdr d) 98 | nil 99 | (cons 100 | (+ (list (car it) (cadr it)) 101 | (self (cddr it) nil nil)) 102 | acc)))) 103 | (self (cddr d) nil (cons (cadr d) (cons (car d) acc)))))) 104 | (cdr d) nil nil))))) 105 | 106 | (mac desc defs 107 | `(arc.unit::runner 108 | ,(expand-desc defs) 109 | (***lex-ns***))) 110 | 111 | ;; (desc "ABC test1" 112 | ;; :ns arc.compiler 113 | ;; :f string 114 | ;; (desc "ABC test 10" 115 | ;; :ns arc.compiler 116 | ;; (test "should return -1 when the value is not present" 117 | ;; (is 118 | ;; :f string 119 | ;; (+ 1 2) "3"))) 120 | ;; (test "should xxx")) 121 | ;; => 122 | ;; (runner 123 | ;; `((desc "ABC test1" 124 | ;; :ns arc.compiler 125 | ;; :f ,string 126 | ;; (desc "ABC test 10" 127 | ;; :ns arc.compiler 128 | ;; (test "should return -1 when the value is not present" 129 | ;; (,is 130 | ;; :f ,string 131 | ;; (+ 1 2) "3"))) 132 | ;; (test "should xxx"))) 133 | ;; (***lex-ns***)) -------------------------------------------------------------------------------- /src/box.js: -------------------------------------------------------------------------------- 1 | var Box = classify('Box', { 2 | property: { 3 | v: null 4 | }, 5 | method: { 6 | init: function(v) { 7 | this.v = v; 8 | }, 9 | unbox: function() { 10 | return this.v; 11 | }, 12 | setbox: function(v) { 13 | this.v = v; 14 | } 15 | } 16 | }); 17 | ArcJS.Box = Box; 18 | -------------------------------------------------------------------------------- /src/call.js: -------------------------------------------------------------------------------- 1 | var Call = classify("Call", { 2 | property: { 3 | name: null, 4 | fn: null, 5 | args: null 6 | }, 7 | method: { 8 | init: function(fn, name, args) { 9 | if (fn) this.fn = fn; 10 | else if (name) this.name = name; 11 | else throw new Error("Must be set valid fn or name"); 12 | this.args = args; 13 | }, 14 | codegen: function() { 15 | var code; 16 | if (this.name) { 17 | code = [ 18 | ['refer-global', this.name], 19 | ['indirect'], 20 | ['apply'] 21 | ]; 22 | } else { 23 | code = [ 24 | ['constant', this.fn], 25 | ['apply'] 26 | ]; 27 | } 28 | var l = this.args.length; 29 | code.unshift(['argument']); 30 | code.unshift(['constant', l]); 31 | for (var i=l-1; -1 < i; i--) { 32 | code.unshift(['argument']); 33 | code.unshift(['constant', this.args[i]]); 34 | } 35 | return code; 36 | } 37 | } 38 | }); 39 | ArcJS.Call = Call; 40 | -------------------------------------------------------------------------------- /src/char.js: -------------------------------------------------------------------------------- 1 | var Char = classify("Char", { 2 | static: { 3 | ESCAPED_CHAR_TBL: {}, 4 | tbl: {}, 5 | get: function(n) { 6 | var c = null; 7 | if (!(c = this.tbl[n])) { 8 | c = new Char(n); 9 | this.tbl[n] = c; 10 | } 11 | return c; 12 | }, 13 | stringify: function(c) { 14 | var x; 15 | if (x = Char.ESCAPED_CHAR_TBL[c.c]) return "#\\" + x; 16 | return "#\\" + c.c; 17 | } 18 | }, 19 | property: { c: null }, 20 | method: { 21 | init: function(c) { 22 | this.c = c; 23 | } 24 | } 25 | }); 26 | ArcJS.Char = Char; 27 | todos_after_all_initialized.push(function() { 28 | // Char.ESC is inverted Reader.ESC 29 | var resc = Reader.ESCAPED_CHAR_TBL, cesc = Char.ESCAPED_CHAR_TBL; 30 | for ( var n in resc ) { 31 | cesc[resc[n]] = n; 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /src/closure.js: -------------------------------------------------------------------------------- 1 | var Closure = classify('Closure', { 2 | property: { 3 | name: null, 4 | body: null, 5 | pc: 0, 6 | arglen: 0, 7 | dotpos: 0, 8 | closings: [], 9 | namespace: null 10 | }, 11 | method: { 12 | init: function(body, pc, closinglen, arglen, dotpos, stack, stack_pointer, namespace) { 13 | this.body = body; 14 | this.pc = pc; 15 | this.arglen = arglen; 16 | this.dotpos = dotpos; 17 | for (var i = 0; i all (nothing to do) 118 | } else { 119 | // all -> not-all 120 | this.exports = _copy(this.primary); 121 | this.exports_by_type = _copy(this.primary_by_type, 2); 122 | } 123 | } else { 124 | // all -> all or not-all -> not-all (nothing to do) 125 | } 126 | }, 127 | setBox: function(name, val) { 128 | var type_name = type(val).name; 129 | var ns = (name.match(/\*\*\*.+\*\*\*/)) ? NameSpace.global_ns : this; 130 | if (name in ns.primary) ns.primary[name].v = val; 131 | else ns.primary[name] = new Box(val); 132 | var by_type = ns.primary_by_type[type_name] || {}; 133 | if (name in by_type) by_type[name].v = val; 134 | else by_type[name] = new Box(val); 135 | ns.primary_by_type[type_name] = by_type; 136 | if (ns.export_all || -1 < ns.export_names.indexOf(name)) { 137 | if (name in ns.exports) ns.exports[name].v = val; 138 | else ns.exports[name] = new Box(val); 139 | var by_type = ns.exports_by_type[type_name] || {}; 140 | if (name in by_type) by_type[name].v = val; 141 | else by_type[name] = new Box(val); 142 | ns.exports_by_type[type_name] = by_type; 143 | } 144 | }, 145 | get: function(name) { 146 | var v = this.primary[name]; 147 | if (v) return v; 148 | for (var i = this.imports.length-1; -1\"","restore","3","+","msec","-","\"[OK]\"","\"in\"","\"ms\"","10","caadr","(prn \"\")","9","set-timer","caddr","cadddr","apply","unknown-type",":ns",":f","unknown-option","\"** \"","\" tests done. succ/fail => \"","\"/\"","\" in \"","\" ms\"","<","\" tests failed\"","self","runner","quasiquote","list","nrev","f","unquote","do","***lex-ns***","expand-desc","arc.unit::runner","((***lex-ns***))"]); 15 | -------------------------------------------------------------------------------- /test/compiling-compiler.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | arc-js : test-compiling-compiler 5 | 6 | 7 | 8 |

compiling compiler

9 | Compiled code is here.

10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/compiling-compiler.js: -------------------------------------------------------------------------------- 1 | var vm = new ArcJS.VM(); 2 | var cadr = ArcJS.cadr; 3 | 4 | function compile(expr) { 5 | var asm = [ 6 | ['frame', 8], 7 | ['constant', expr], 8 | ['argument'], 9 | ['constant', 1], 10 | ['argument'], 11 | ['refer-global', 'compile'], 12 | ['indirect'], 13 | ['apply'], 14 | ['halt'] 15 | ]; 16 | vm.cleanup(); 17 | vm.set_asm(asm); 18 | return vm.run(); 19 | } 20 | 21 | function evaluate(expr) { 22 | var compiled = compile(expr); 23 | vm.cleanup(); 24 | vm.load(compiled); 25 | return vm.run(); 26 | } 27 | 28 | function evaluate_code(code) { 29 | return evaluate(vm.reader.read(code)); 30 | } 31 | 32 | var log = ''; 33 | function pr(src) { 34 | log += src + '
'; 35 | $('#stage').html(log); 36 | } 37 | 38 | function compile_file(url) { 39 | $.ajax({ 40 | url: url, 41 | type: 'GET' 42 | }).done(function(r){ 43 | vm.reader.load_source(r); 44 | var exprs = []; 45 | while (true) { 46 | var expr = vm.reader.read(); 47 | if (expr === ArcJS.Reader.EOF) break; 48 | exprs.push(expr); 49 | } 50 | var ts = new Date(); 51 | var i = 0, l=exprs.length; 52 | setTimeout(function compile1() { 53 | function add(a, b) { return a + b; } 54 | if (i < l) { 55 | var s = new Date(); 56 | compile(exprs[i]); 57 | var e = new Date(); 58 | pr('COMPILED: ' + cadr(exprs[i]).name + ' ... passed ' + (e - s) + ' ms.'); 59 | pr(''); 60 | i++; 61 | setTimeout(compile1, 0); 62 | } else { 63 | var te = new Date(); 64 | var hist = load() || []; 65 | var total = (te - ts); 66 | hist.push(total); 67 | pr('TOTAL ' + total + ' ms have passed.'); 68 | pr('AVG: ' + (hist.reduce(add, 0) / hist.length) + ' (' + hist.length + ' times).'); 69 | save(hist); 70 | } 71 | }, 0); 72 | }).error(function(r) { 73 | throw new Error(r.responseText); 74 | }); 75 | } 76 | 77 | function save(x) { 78 | localStorage.setItem('savings', JSON.stringify(x)); 79 | } 80 | 81 | function load() { 82 | return JSON.parse(localStorage.getItem('savings')); 83 | } 84 | 85 | function clear() { 86 | localStorage.removeItem('savings'); 87 | } 88 | 89 | $(function run() { 90 | compile_file('../src/arc/compiler.arc'); 91 | $("#clear-hist").click(clear); 92 | }); 93 | -------------------------------------------------------------------------------- /test/unit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | arc-js : unit-test-runner 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/unit/arc/ns.arc: -------------------------------------------------------------------------------- 1 | (ns (defns tests.arc.ns :import arc.unit)) 2 | 3 | (desc "namespace" 4 | 5 | (test "bound" 6 | (do (defns A)) 7 | (is :ns A 8 | (assign x 1) 1 9 | (bound 'x) t) 10 | (is :ns user 11 | (bound 'x) nil)) 12 | 13 | (test "shadowing" 14 | (do (defns A)) 15 | (is :ns A 16 | (assign x 1) 1 17 | (bound 'x) t) 18 | (do (defns B)) 19 | (is :ns B 20 | (assign x 2) 2) 21 | (do (defns C)) 22 | (is :ns C 23 | (assign x 3) 3) 24 | (do (defns D :import A B C)) 25 | (is :ns D 26 | x 3) 27 | (is :ns C 28 | x 3) 29 | (is :ns B 30 | x 2) 31 | (is :ns A 32 | x 1) 33 | (is :ns user 34 | (bound 'x) nil)) 35 | 36 | (test "global" 37 | (do (defns A)) 38 | (is :ns A 39 | (assign X 10) 10 40 | (assign ***X*** 20) 20 41 | X 10 42 | ***X*** 20) 43 | (do (ns 'user)) 44 | (is :ns user 45 | (bound 'X) nil 46 | (bound '***X***) t 47 | ***X*** 20 48 | (assign ***X*** 30) 30 49 | ***X*** 30) 50 | (do (ns 'A)) 51 | (is :ns A 52 | ***X*** 30)) 53 | 54 | (test "***curr-ns***" 55 | (do (defns A) 56 | (do (ns 'A) (def x () (***curr-ns***)))) 57 | (is :ns A 58 | (is (x) (ns 'A)) t) 59 | (do (defns B :import A)) 60 | (is :ns B 61 | (is (x) (ns 'B)) t)) 62 | 63 | (test "***macro***" 64 | (do (do (ns 'user) 65 | (mac m (a b) `(- ,a ,b))) 66 | (do (ns (defns A)) 67 | (mac m (a b) `(+ ,a ,b)))) 68 | (is :ns A 69 | (m 10 20) 30) 70 | (is :ns user 71 | (m 10 20) -10)) 72 | 73 | (test "export and :: syntax" 74 | (do (do (ns (defns A :export a b)) 75 | (= a 10 b 20 c 30)) 76 | (defns B :import A :export c)) 77 | (is :ns B 78 | a 10 79 | b 20 80 | (bound 'c) nil 81 | A::c 30 82 | (= c 40) 40 83 | c 40 84 | B::c 40) 85 | (do (defns C :import A B)) 86 | (is :ns C 87 | a 10 88 | b 20 89 | c 40 90 | A::c 30)) 91 | 92 | (desc "extend" 93 | 94 | (test "basic" 95 | (do 96 | (do (ns (defns A :export a b)) 97 | (= a 10 b 20 c 30) 98 | (ns (defns B :import A)) 99 | (= d 40 f 50))) 100 | (is :ns B 101 | a 10 102 | b 20 103 | (bound 'c) nil 104 | A::c 30)) 105 | 106 | (test "can access parent's import" 107 | (do (defns C :extend B)) 108 | (is :ns C 109 | a 10 110 | b 20 111 | (bound 'c) nil)) 112 | 113 | (test "can access parent's private" 114 | (do (do (ns (defns D :extend A)) 115 | (= dd 10 ff 20))) 116 | (is :ns D 117 | a 10 118 | b 20 119 | (bound 'c) t 120 | c 30 121 | D::c 30)) 122 | 123 | (test "parent not-all -> me all" 124 | (do (defns E :import D)) 125 | (is :ns E 126 | a 10 127 | b 20 128 | (bound 'c) nil 129 | dd 10 130 | ff 20)) 131 | 132 | (test "parent not-all -> me not-all" 133 | (do (defns F :extend A :export c)) 134 | (is :ns F 135 | a 10 136 | b 20 137 | c 30) 138 | (do (defns G :import F)) 139 | (is :ns G 140 | a 10 141 | b 20 142 | (bound 'c) nil) 143 | 144 | ;; even if the ns export the var, 145 | ;; it doesn't export extended private var automatically. 146 | ;; if you want to do this. 147 | 148 | ;; define c in itself as extended private c. 149 | (do (do (ns 'F) (= c c))) 150 | 151 | (is :ns G 152 | c 30)) 153 | 154 | (test "parent all -> me all" 155 | (do (do (ns (defns H :extend B)) 156 | (= g 60))) 157 | (is :ns H 158 | (bound 'c) nil 159 | a 10 160 | b 20 161 | f 50) 162 | (do (defns I :import H)) 163 | (is :ns I 164 | (bound 'a) nil 165 | (bound 'b) nil 166 | d 40 167 | f 50 168 | g 60)) 169 | 170 | (test "parent all -> me not-all" 171 | (do (do (ns (defns J :extend B :export g)) 172 | (= g 60 h 70)) 173 | (defns K :import J)) 174 | (is :ns K 175 | g 60 176 | (bound 'h) nil 177 | (bound 'a) nil 178 | (bound 'b) nil 179 | d 40 180 | f 50 181 | g 60 182 | (bound 'h) nil))) 183 | 184 | (test "deftf" 185 | (do (do (ns (defns A)) 186 | (deftf string (str n) (+ str n)))) 187 | (is :ns A 188 | ("abc" "def") "abcdef") 189 | (do (do (ns (defns B)) 190 | (deftf string (str n) (ref str (* n 2))))) 191 | (is :ns B 192 | ("abcd" 1) #\c) 193 | (is :ns A 194 | ("abc" 1) "abc1") 195 | (is :ns B 196 | ("abc" 1) #\c) 197 | (is :ns user 198 | ("abc" 1) #\b)) 199 | 200 | (test "defss" 201 | (do (do (ns (defns A :export test-ss)) 202 | (defss test-ss #/^(\d+)\.\.\.(\d+)$/ (start end) 203 | `(range ,start ,end)) 204 | (defss test-ss-2 #/^(\d+)%(\d+)$/ (x y) 205 | `(arc.math::mod ,x ,y)))) 206 | (iso :ns A 207 | 10...20 '(10 11 12 13 14 15 16 17 18 19 20) 208 | 10%3 1) 209 | 210 | (do (do (ns (defns B :import A)))) 211 | 212 | (iso :ns B 213 | 1...10 '(1 2 3 4 5 6 7 8 9 10) 214 | (macex '10%3) '10%3)) 215 | 216 | (test "redef" 217 | (do (do (ns (defns A :export a)) 218 | (def a () 10) 219 | (def b () (a)))) 220 | (is :ns A 221 | (b) 10 222 | (do (def a () 20) 223 | (b)) 20) 224 | (do (do (ns (defns B :import A)) 225 | (def c () (a)))) 226 | (is :ns B 227 | (c) 20) 228 | (do (do (ns 'A) 229 | (def a () 30))) 230 | (is :ns B 231 | (c) 30)) 232 | 233 | ) 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /tools/arc-compiler-arc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import sys 4 | import os 5 | import re 6 | import argparse 7 | import json 8 | from subprocess import Popen, PIPE 9 | from datetime import datetime 10 | 11 | def main(): 12 | argparser = argparse.ArgumentParser() 13 | argparser.add_argument('-o', type=str, metavar='file', help='output file.') 14 | argparser.add_argument('file', nargs='+', type=str, help='input files.', metavar='file') 15 | options = argparser.parse_args() 16 | if options.o is not None: 17 | out = open(options.o, 'w') 18 | else: 19 | out = sys.stdout 20 | try: 21 | out.write("""// This is an auto generated file. 22 | // Compiled from %s. 23 | // DON'T EDIT !!! 24 | preload.push.apply(preload, [""" % (map(os.path.realpath, options.file),)) 25 | for file in options.file: 26 | with open(file, 'r') as _input: 27 | compiler_path = os.path.dirname(os.path.realpath(__file__)) + "/helper-compiler/compiler-file.arc" 28 | p = Popen(["arc", compiler_path], stdout=PIPE, stdin=_input, stderr=PIPE) 29 | res, err = p.communicate() 30 | if 0 < len(err.decode('utf-8')): 31 | raise Exception(err.decode('utf-8')) 32 | lines = filter(lambda l: l != '', res.decode('utf-8').split('\n')) 33 | for line in lines: 34 | out.write('\n' + line) 35 | out.write("]);") 36 | except: 37 | if options.o is not None: 38 | out.close() 39 | os.unlink(options.o) 40 | raise 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /tools/helper-compiler/compiler-file.arc: -------------------------------------------------------------------------------- 1 | (load "/Users/smihica/code/arc-js/tools/helper-compiler/compiler.arc") 2 | 3 | (= ops 4 | '(frame close test conti shift constant argument 5 | refer-let refer-local refer-free refer-global 6 | refer-nil refer-t enter-let exit-let assign-let assign-local assign-global 7 | box indirect apply return continue-return halt)) 8 | 9 | (mac _wrap body 10 | `(do (write (pos top ops)) 11 | ,@(if body 12 | (cons 13 | '(pr ",") 14 | (intersperse '(pr ",") body))) 15 | (pr ","))) 16 | 17 | (def arc-compiler () 18 | (whilet exp (read) 19 | (let asm (do-compile exp) 20 | (pr "[") 21 | (each c asm 22 | (let top (car c) 23 | (reccase 24 | c 25 | (frame (ret) (_wrap (pr ret))) 26 | (close (n v d b) (_wrap (pr n) (pr v) (pr d) (pr b))) 27 | (test (n) (_wrap (pr n))) 28 | (conti (n) (_wrap (pr n))) 29 | (shift (n m) (_wrap (pr n) (pr m))) 30 | (constant (obj) (_wrap (write (tostring (write obj))))) 31 | (argument () (_wrap)) 32 | (refer-let (n m) (_wrap (pr n) (pr m))) 33 | (refer-local (n) (_wrap (pr n))) 34 | (refer-free (n) (_wrap (pr n))) 35 | (refer-global (n) (_wrap (write (string n)))) 36 | (refer-nil () (_wrap)) 37 | (refer-t () (_wrap)) 38 | (enter-let () (_wrap)) 39 | (exit-let (n) (_wrap (pr n))) 40 | (assign-let (n m) (_wrap (pr n) (pr m))) 41 | (assign-local (n) (_wrap (pr n))) 42 | (assign-free (n) (_wrap (pr n))) 43 | (assign-global (n) (_wrap (write (string n)))) 44 | (box (n) (_wrap (pr n))) 45 | (indirect () (_wrap)) 46 | (apply () (_wrap)) 47 | (return (n) (_wrap (pr n))) 48 | (halt () (_wrap)) 49 | nil))) 50 | (pr "],") 51 | (prn)))) 52 | 53 | (arc-compiler) 54 | -------------------------------------------------------------------------------- /tools/helper-compiler/compiler-server.arc: -------------------------------------------------------------------------------- 1 | (load "/Users/smihica/code/arc-js/tools/helper-compiler/compiler.arc") 2 | 3 | (defop arc-compiler req 4 | (let asm (do-compile (read (alref (req 'args) "code"))) 5 | (prn "(") 6 | (each c asm 7 | (write c) 8 | (prn)) 9 | (pr ")"))) 10 | 11 | (serve 8800) 12 | -------------------------------------------------------------------------------- /tools/helper-compiler/test-vm.arc: -------------------------------------------------------------------------------- 1 | (load "/Users/smihica/code/arc-js/tools/helper-compiler/util.arc") 2 | 3 | (= stack (n-of 1000 0)) 4 | 5 | (def _push (x s) 6 | (= (stack s) x) 7 | (+ s 1)) 8 | 9 | (def index (s i) 10 | (let idx (- s i 1) 11 | (if (< idx 0) 12 | ((map cdr (rev primitives)) (- (abs idx) 13 | 1 ;; indexize (1 -> 0) 14 | 1 ;; ignore arg-len buffer. 15 | )) 16 | (stack idx)))) 17 | 18 | (def index-set (s i v) 19 | (= (stack (- (- s i) 1)) v)) 20 | 21 | (def range-get (from to) 22 | (map stack (range from to))) 23 | 24 | (def show-stack (s) 25 | ((afn (i s) 26 | (when (< -1 i) 27 | (pr i ":" (let s (stack i) 28 | ((afn (s) 29 | (if (is (type s) 'cons) 30 | (+ "(" (self (car s)) " ... )") 31 | (tostring (pr s)))) s)) 32 | (if (is s i) " (s)" "") 33 | "\n") 34 | (self (- i 1) s))) 35 | 20 s)) 36 | 37 | (def closure (body n s) 38 | (let v (n-of (+ n 1) 0) 39 | (= (v 0) body) 40 | (for i 1 n (= (v i) (index s (- i 1)))) 41 | v)) 42 | 43 | (def continuation (s) 44 | (closure `(refer-local 0 (nuate ,(save-stack s) (return 0))) 0 '())) 45 | (def save-stack (s) (firstn s stack)) 46 | (def restore-stack (v) 47 | (= stack (+ v (nthcdr (len v) stack))) 48 | (len v)) 49 | 50 | (= step 0) 51 | (def show-step (x) 52 | (do1 53 | (pr "step: " step " opcode: " (car x) "\n") 54 | (= step (+ step 1)))) 55 | 56 | (def box (x) (list x)) 57 | (def set-box (b x) (= (car b) x)) 58 | (def unbox (x) (car x)) 59 | 60 | (def closure-body (c) (c 0)) 61 | (def index-closure (c n) (c (+ n 1))) 62 | 63 | (def shift-args (n m s) 64 | ((afn (i) 65 | (unless (< i 0) 66 | (index-set s (+ i m) (index s i)) 67 | (self (- i 1)))) 68 | (- n 1)) 69 | (- s m)) 70 | 71 | (def vm (a x f c s) 72 | (if debug-mode 73 | (do 74 | (pr "a:" a "\n") 75 | (pr "x:" x "\n") 76 | (pr "f:" f "\n") 77 | (pr "c:" c "\n") 78 | (pr "s:" s "\n") 79 | (show-step x) 80 | (show-stack s) 81 | (aif (read) 82 | (case it 83 | q nil 84 | n (vm-tick a x f c s)))) 85 | (vm-tick a x f c s))) 86 | 87 | (def vm-tick (a x f c s) 88 | (reccase 89 | x 90 | (halt () a) 91 | (refer-local (n x) (vm (index f (+ n 1)) x f c s)) 92 | (refer-free (n x) (vm (index-closure c n) x f c s)) 93 | (indirect (x) (vm (unbox a) x f c s)) 94 | (constant (obj x) (vm obj x f c s)) 95 | (close (n body x) (vm (closure body n s) x f c (- s n))) 96 | (box (n x) (do (index-set s (+ n 1) 97 | (box (index s (+ n 1)))) 98 | (vm a x f c s))) 99 | (test (then else) (vm a (if a then else) f c s)) 100 | (assign-local (n x) (do (set-box (index f (+ n 1)) a) 101 | (vm a x f c s))) 102 | (assign-free (n x) (do (set-box (index-closure c n) a) 103 | (vm a x f c s))) 104 | (conti (x) (vm (continuation s) x f c s)) 105 | (nuate (stack x) (vm a x f c (restore-stack stack))) 106 | (frame (ret x) (vm a x f c (_push ret (_push f (_push c s))))) 107 | (argument (x) (vm a x f c (_push a s))) 108 | (shift (n m x) (vm a x f c (shift-args n m s))) 109 | (apply () (if (is (type a) 'cons) 110 | (vm a (closure-body a) s a s) 111 | (let var-len (index s 0) 112 | (vm (apply a (range-get (- s 1 var-len) 113 | (- s 2))) 114 | (index s (+ var-len 1)) 115 | (index s (+ var-len 2)) 116 | (index s (+ var-len 3)) 117 | (- s 118 | var-len ;; vars 119 | 1 ;; var-len buffer 120 | 1 ;; ret 121 | 1 ;; f 122 | 1 ;; c 123 | ))))) 124 | (return (x) (let s (- s x) 125 | (vm a (index s 0) (index s 1) (index s 2) (- s 3)))) 126 | (pr "Error: I don't know how to do. " x "\n"))) 127 | 128 | (def evaluate (x) 129 | (= step 0) 130 | (= stack (n-of 1000 0)) 131 | (vm '() 132 | (do-compile x) 133 | 0 134 | '() 135 | (_push 0 0))) 136 | 137 | 138 | (mac unit-tests tests 139 | `(do 140 | (= debug-mode nil) 141 | ,@(map (fn (x) 142 | `(if (is (evaluate ',x) ,x) 143 | (pr "[PASS]: " ,x "\t" ',x "\n") 144 | (pr "!!! FAIL: " ',x "\n"))) 145 | tests) 146 | (= debug-mode t) 147 | nil)) 148 | 149 | (def run-tests () 150 | (unit-tests 151 | ;; value 152 | 1 153 | 20 154 | 155 | ;; exp 156 | (+ 1 2) 157 | (+ (/ 1 2) 3) 158 | (- 1 2 3) 159 | (+ 1 (+ 2 3)) 160 | (+ (- 3 4) (+ 1 (- 1 (* 3 2)))) 161 | 162 | ;; fn 163 | ((fn (a b) (+ a b)) 10 20) 164 | (if 'a 1 2) 165 | (if nil 1 2) 166 | 167 | ((fn (c d) 168 | (* c 169 | ((fn (a b) (+ (- d c) a b d)) 170 | d (+ d d)))) 171 | 10 3) 172 | 173 | ;; multiple exp 174 | ((fn (a b) 175 | (+ a b) 176 | (- a b) 177 | (/ a b)) 178 | 20 10) 179 | 180 | ;; do 181 | ((fn (a b) 182 | (do (+ 1 2) 183 | (+ a b))) 184 | 10 20) 185 | 186 | ;; ccc 187 | (+ 1 (ccc (fn (c) (+ 3 5) (c (* 8 3))))) 188 | 189 | ((fn (x) 190 | ((fn (cc) 191 | (assign x (+ (ccc (fn (c) (assign cc c) (c 1))) x)) 192 | (if (< x 4) (cc 2) x)) 193 | nil)) 194 | 0) 195 | 196 | ;; ng 197 | ;((fn (x cc) 198 | ;(assign x (+ x (ccc (fn (c) (assign cc c) (c 1))))) 199 | ;(if (< x 10) 200 | ;(cc 2) 201 | ;x)) 202 | ;0 nil) 203 | 204 | ;; assign-local 205 | ((fn (a b) 206 | (assign a 10) 207 | (* a b)) 208 | 1 3) 209 | 210 | ((fn (a b) 211 | (assign b 30) 212 | (* a b)) 213 | 1 3) 214 | 215 | ((fn (a b) 216 | (assign a 10) 217 | (assign b 30) 218 | (* a b)) 219 | 1 3) 220 | 221 | ;; assign-free 222 | ((fn (a b) 223 | ((fn () 224 | (assign a 10))) 225 | (* a b)) 226 | 1 3) 227 | 228 | ;; assingn mixed 229 | ((fn (a) 230 | ((fn (b) 231 | ((fn (c d) 232 | (assign a 100) 233 | ((fn (e) 234 | (assign e (+ a e)) 235 | (assign c 20) 236 | (+ a b c d e)) 237 | 5)) 238 | 3 4)) 239 | 2)) 240 | 1) 241 | 242 | )) 243 | 244 | ;; vm2 ----------------------------------------------------------- 245 | 246 | (def closure2 (x p n s) 247 | (let v (n-of (+ n 2) 0) 248 | (= (v 0) x) 249 | (= (v 1) p) 250 | (for i 0 (- n 1) (= (v (+ i 2)) (index s i))) 251 | v)) 252 | (def closure-body2 (c) (c 0)) 253 | (def closure-pc2 (c) (c 1)) 254 | (def index-closure2 (c n) (c (+ n 2))) 255 | (def continuation2 (s) 256 | (closure2 `((refer-local 0) (nuate ,(save-stack s)) (return 0)) 0 0 '())) 257 | 258 | (def vm2 (x p a f c s) 259 | (if debug-mode 260 | (do 261 | (prn "x:" x) 262 | (prn "p:" p) 263 | (prn "a:" a) 264 | (prn "f:" f) 265 | (prn "c:" c) 266 | (prn "s:" s) 267 | (show-step x) 268 | (show-stack s) 269 | (aif (read) 270 | (case it 271 | q nil 272 | n (vm-tick2 x p a f c s)))) 273 | (vm-tick2 x p a f c s))) 274 | 275 | (def vm-tick2 (x p a f c s) 276 | (let op (x p) 277 | (reccase 278 | op 279 | (halt () a) 280 | (refer-local (n) (vm2 x (inc p) (index f (+ n 1)) f c s)) 281 | (refer-free (n) (vm2 x (inc p) (index-closure2 c n) f c s)) 282 | (indirect () (vm2 x (inc p) (unbox a) f c s)) 283 | (constant (obj) (vm2 x (inc p) obj f c s)) 284 | (close (n b) (vm2 x (+ p b) (closure2 x (+ p 1) n s) f c (- s n))) 285 | (box (n) (do (index-set s (+ n 1) (box (index s (+ n 1)))) 286 | (vm2 x (inc p) a f c s))) 287 | (test (n) (vm2 x (if a (inc p) (+ p n)) a f c s)) 288 | (assign-local (n) (do (set-box (index f (+ n 1)) a) 289 | (vm2 x (inc p) a f c s))) 290 | (assign-free (n) (do (set-box (index-closure2 c n) a) 291 | (vm2 x (inc p) a f c s))) 292 | (frame (ret) (vm2 x (inc p) a f c (_push (list x (+ p ret)) 293 | (_push f 294 | (_push c s))))) 295 | (argument () (vm2 x (inc p) a f c (_push a s))) 296 | (shift (n m) (vm2 x (inc p) a f c (shift-args n m s))) 297 | (apply () (if (is (type a) 'cons) 298 | (vm2 (closure-body2 a) (closure-pc2 a) a s a s) 299 | (let var-len (index s 0) 300 | (let xp (index s (+ var-len 1)) 301 | (vm2 (car xp) 302 | (cadr xp) 303 | (apply a (range-get (- s 1 var-len) 304 | (- s 2))) 305 | (index s (+ var-len 2)) 306 | (index s (+ var-len 3)) 307 | (- s var-len 4)))))) 308 | (return (n) (let ns (- s n) 309 | (let xp (index ns 0) 310 | (vm2 (car xp) 311 | (cadr xp) 312 | a 313 | (index ns 1) 314 | (index ns 2) 315 | (- ns 3))))) 316 | 317 | (conti () (vm2 x (inc p) (continuation2 s) f c s)) 318 | (nuate (stack) (vm2 x (inc p) a f c (restore-stack stack))) 319 | 320 | (prn "Error: I don't know how to do. ")))) 321 | 322 | (def evaluate2 (x) 323 | (= step 0) 324 | (= stack (n-of 1000 0)) 325 | (vm2 (preproc (do-compile x) 0) 326 | 0 327 | '() 328 | 0 329 | '() 330 | (_push 0 0))) 331 | 332 | (mac unit-tests2 tests 333 | `(do 334 | (= debug-mode nil) 335 | ,@(map (fn (x) 336 | `(if (is (evaluate2 ',x) ,x) 337 | (pr "[PASS]: " ,x "\t" ',x "\n") 338 | (pr "!!! FAIL: " ',x "\n"))) 339 | tests) 340 | (= debug-mode t) 341 | nil)) 342 | 343 | (unit-tests2 344 | ;; value 345 | 1 346 | 20 347 | 348 | ;; exp 349 | (+ 1 2) 350 | (+ (/ 1 2) 3) 351 | (- 1 2 3) 352 | (+ 1 (+ 2 3)) 353 | (+ (- 3 4) (+ 1 (- 1 (* 3 2)))) 354 | 355 | ;; fn 356 | ((fn (a b) (+ a b)) 10 20) 357 | (if 'a 1 2) 358 | (if nil 1 2) 359 | 360 | ((fn (c d) 361 | (* c 362 | ((fn (a b) (+ (- d c) a b d)) 363 | d (+ d d)))) 364 | 10 3) 365 | 366 | ;; multiple exp 367 | ((fn (a b) 368 | (+ a b) 369 | (- a b) 370 | (/ a b)) 371 | 20 10) 372 | 373 | ;; do 374 | ((fn (a b) 375 | (do (+ 1 2) 376 | (+ a b))) 377 | 10 20) 378 | 379 | ;; ccc 380 | (+ 1 (ccc (fn (c) (+ 3 5) (c (* 8 3))))) 381 | 382 | ;; ng 383 | ((fn (x) 384 | ((fn (cc) 385 | (assign x (+ (ccc (fn (c) (assign cc c) (c 1))) x)) 386 | (if (< x 4) (cc 2) x)) 387 | nil)) 388 | 0) 389 | 390 | ;; ng 391 | ;((fn (x cc) 392 | ;(assign x (+ x (ccc (fn (c) (assign cc c) (c 1))))) 393 | ;(if (< x 10) 394 | ;(cc 2) 395 | ;x)) 396 | ;0 nil) 397 | 398 | ;; assign-local 399 | ((fn (a b) 400 | (assign a 10) 401 | (* a b)) 402 | 1 3) 403 | 404 | ((fn (a b) 405 | (assign b 30) 406 | (* a b)) 407 | 1 3) 408 | 409 | ((fn (a b) 410 | (assign a 10) 411 | (assign b 30) 412 | (* a b)) 413 | 1 3) 414 | 415 | ;; assign-free 416 | ((fn (a b) 417 | ((fn () 418 | (assign a 10))) 419 | (* a b)) 420 | 1 3) 421 | 422 | ;; assingn mixed 423 | ((fn (a) 424 | ((fn (b) 425 | ((fn (c d) 426 | (assign a 100) 427 | ((fn (e) 428 | (assign e (+ a e)) 429 | (assign c 20) 430 | (+ a b c d e)) 431 | 5)) 432 | 3 4)) 433 | 2)) 434 | 1) 435 | ) 436 | -------------------------------------------------------------------------------- /tools/helper-compiler/util.arc: -------------------------------------------------------------------------------- 1 | (mac reccase (expr . pats) 2 | (withs (p (split pats (- (len pats) 1)) 3 | f (car p) l (cadr p)) 4 | `(case (car ,expr) 5 | ,@(+ (mappend 6 | (fn (pat) `(,(car pat) (apply (fn ,@(cdr pat)) (cdr ,expr)))) 7 | f) 8 | l)))) 9 | 10 | (def set-minus (s1 s2) 11 | (if s1 12 | (if (mem (car s1) s2) 13 | (set-minus (cdr s1) s2) 14 | (cons (car s1) (set-minus (cdr s1) s2))))) 15 | 16 | (def set-intersect (s1 s2) 17 | (if s1 18 | (if (mem (car s1) s2) 19 | (cons (car s1) (set-intersect (cdr s1) s2)) 20 | (set-intersect (cdr s1) s2)))) 21 | 22 | (= primitives (list (cons 'nil nil) 23 | (cons '+ +) (cons '- -) (cons '* *) (cons '/ /) 24 | (cons '< <) (cons '> >) (cons '<= <=) (cons '>= >=) 25 | (cons 'no no) (cons 'is is))) 26 | 27 | (def dotted-to-proper (l) 28 | (if (no l) nil 29 | (atom l) (cons l nil) 30 | (cons (car l) (dotted-to-proper (cdr l))))) 31 | 32 | (def dotted-pos (lis) 33 | ((afn (l n) 34 | (if (no l) -1 35 | (atom l) n 36 | (self (cdr l) (inc n)))) 37 | lis 0)) 38 | -------------------------------------------------------------------------------- /tools/jsconstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ## This is a JavaScript concatenate utility. 4 | ## Copylight (C) smihica Mit Licence. 5 | 6 | ## 7 | ## Providing syntax. (javascript) 8 | ## 9 | ## 1. #include "./abc.js" 10 | ## 11 | ## 2. #ifdef VAR1 12 | ## console.log('VAR1 is set'); 13 | ## #elif VAR2 14 | ## console.log('VAR2 is set'); 15 | ## #else 16 | ## console.log('Neither VAR1 nor VAR2 is set.') 17 | ## #endif 18 | ## 19 | ## 3. var def = require("./def.js"); 20 | ## 21 | 22 | 23 | import sys, os, re, argparse, random 24 | from cStringIO import StringIO 25 | 26 | class ApplicationException(Exception): 27 | pass 28 | 29 | def gencharset(spec): 30 | retval = u'' 31 | for item in re.finditer(ur'([^\\-]|\\-|\\\\)(?:-([^\\-]|\\-|\\\\))?', spec): 32 | if item.group(2): 33 | retval += ''.join(unichr(c) for c in range(ord(item.group(1)), ord(item.group(2)) + 1)) 34 | else: 35 | retval += item.group(1) 36 | return retval 37 | 38 | class IDGenerator(object): 39 | INITIAL_CHARS = gencharset("A-Za-z_") 40 | SUCCEEDING_CHARS = gencharset("0-9A-Za-Z_") 41 | 42 | def __init__(self): 43 | self.generated = set() 44 | 45 | def __call__(self): 46 | retval = random.choice(self.__class__.INITIAL_CHARS) 47 | for i in range(0, 15): 48 | retval += random.choice(self.__class__.SUCCEEDING_CHARS) 49 | return retval 50 | 51 | class Processor(object): 52 | def __init__(self): 53 | self.included_files = set() 54 | self.search_path = set(['.']) 55 | self.libs = {} 56 | self.out = StringIO() 57 | self.idgen = IDGenerator() 58 | 59 | def lookup_file(self, file, includer=None): 60 | for dir in self.search_path: 61 | if os.path.isabs(dir): 62 | path = os.path.join(dir, file) 63 | else: 64 | if includer is None: 65 | raise ApplicationException("Relative path specified but no includer given") 66 | path = os.path.join(os.path.dirname(includer), dir, file) 67 | if os.path.exists(path): 68 | return os.path.normpath(path) 69 | return None 70 | 71 | def in_ifstmt(self, if_stack): 72 | for i in if_stack: 73 | if i[1] != 'MATCHED': 74 | return False 75 | else: 76 | return True 77 | 78 | def is_true_env(self, name): 79 | env = os.getenv(name) 80 | return env and (env.lower() in ('yes', 'y', 'true', '1')) 81 | 82 | def compose_source(self, file, out): 83 | self.included_files.add(file) 84 | with open(file, 'r') as f: 85 | fname = os.path.basename(file) 86 | line_num = 0 87 | if_stack = [] 88 | out.write('/** @file %s { */\n' % fname) 89 | for line in f: 90 | line_num = line_num + 1 91 | macro_line = re.match(r'^#([^ \n]+)\s*([^ \n]*)\s*([^ \n]*)$', line) 92 | if macro_line: 93 | op, arg, arg2 = macro_line.groups() 94 | op = op.strip() 95 | if op == 'include': 96 | if not self.in_ifstmt(if_stack): continue 97 | included_file_name = arg.strip(' "()') 98 | if not included_file_name: 99 | raise ApplicationException("include file is not specified -- %s L%s" % (fname, line_num, )) 100 | included = self.lookup_file(included_file_name, file) 101 | if included in self.included_files: 102 | continue 103 | if included is None: 104 | raise ApplicationException("File not found: %s -- %s L%s" % (included_file_name, fname, line_num, )) 105 | self.compose_source(included, out) 106 | elif op == 'ifdef': 107 | if not arg: 108 | raise ApplicationException("ifdef argument is not specified -- %s L%s" % (fname, line_num, )) 109 | if_stack.append(['ifdef', 'NOT_MATCHED']) 110 | if self.is_true_env(arg): 111 | if_stack[-1][1] = 'MATCHED' 112 | elif op == 'ifndef': 113 | if not arg: 114 | raise ApplicationException("ifdef argument is not specified -- %s L%s" % (fname, line_num, )) 115 | if_stack.append(['ifndef', 'NOT_MATCHED']) 116 | if not self.is_true_env(arg): 117 | if_stack[-1][1] = 'MATCHED' 118 | elif op == 'elif': 119 | if not arg: 120 | raise ApplicationException("elif argument is not specified -- %s L%s" % (fname, line_num, )) 121 | if if_stack[-1][1] == 'NOT_MATCHED': 122 | if ((if_stack[-1][0] == 'ifdef' and self.is_true_env(arg)) or 123 | (if_stack[-1][0] == 'ifndef' and not self.is_true_env(arg))): 124 | if_stack[-1][1] = 'MATCHED' 125 | else: 126 | if_stack[-1][1] = 'CONSUMED' 127 | elif op == 'else': 128 | if if_stack[-1][1] == 'NOT_MATCHED': 129 | if_stack[-1][1] = 'MATCHED' 130 | else: 131 | if_stack[-1][1] = 'CONSUMED' 132 | elif op == 'endif': 133 | if_stack.pop() 134 | else: 135 | raise ApplicationException("unknown macro operation: %s -- %s L%s" % (op, fname, line_num, )) 136 | else: 137 | if not self.in_ifstmt(if_stack): continue 138 | def repl(match): 139 | required_file_name = match.group(2) 140 | required = self.lookup_file(required_file_name, file) 141 | if required is None: 142 | raise ApplicationException("File not found: %s -- %s L%s" % (required_file_name, fname, line_num, )) 143 | pair = self.libs.get(required) 144 | if pair is None: 145 | id = self.idgen() 146 | self.libs[required] = (id, None) 147 | out = StringIO() 148 | self.compose_source(required, out) 149 | pair = self.libs[required] = (id, out.getvalue()) 150 | return "__LIBS__['%s']" % pair[0] 151 | line = re.sub(r'''require\s*\((["])(.+)(\1)\)''', repl, line) 152 | out.write(line) 153 | out.write('/** @} */\n') 154 | 155 | def read(self, file): 156 | self.compose_source(file, self.out) 157 | 158 | def write(self, out): 159 | # TODO: dependency resolution 160 | if self.libs: 161 | out.write("(function () {\n") 162 | out.write("var __LIBS__ = {};\n") 163 | for path, pair in self.libs.iteritems(): 164 | out.write("__LIBS__['%s'] = (function (exports) { (function () { %s })(); return exports; })({});\n" % pair) 165 | first = False 166 | out.write(self.out.getvalue()) 167 | out.write("})();\n") 168 | else: 169 | out.write(self.out.getvalue()) 170 | 171 | def main(): 172 | argparser = argparse.ArgumentParser() 173 | argparser.add_argument('-o', type=str, metavar='file', help='output file.') 174 | argparser.add_argument('file', nargs='+', type=str, help='input files.', metavar='file') 175 | options = argparser.parse_args() 176 | if options.o is not None: 177 | out = open(options.o, 'w') 178 | else: 179 | out = sys.stdout 180 | try: 181 | p = Processor() 182 | for file in options.file: 183 | p.read(os.path.abspath(file)) 184 | p.write(out) 185 | except: 186 | if options.o is not None: 187 | out.close() 188 | os.unlink(options.o) 189 | raise 190 | 191 | if __name__ == '__main__': 192 | try: 193 | main() 194 | except ApplicationException as e: 195 | print >>sys.stderr, e.message 196 | -------------------------------------------------------------------------------- /tools/run-compiler-server: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /Users/smihica/code/anarki 4 | ./arc.sh /Users/smihica/code/arc-js/tools/helper-compiler/compiler-server.arc 5 | -------------------------------------------------------------------------------- /tools/update-watcher: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* 4 | * File watch and exec command cli tool. 5 | * https://gist.github.com/1632134 6 | * copylight (c) hokaccha 7 | * 8 | * Example 9 | * 10 | * $ watcher *.less -- lessc style.less style.css 11 | * 12 | */ 13 | 14 | 'use strict'; 15 | 16 | var fs = require('fs'); 17 | var exec = require('child_process').exec; 18 | var argv = process.argv.slice(2); 19 | var separator = argv.indexOf('--'); 20 | var targets = argv.slice(0, separator); 21 | var command = argv.slice(separator + 1).join(' '); 22 | var tmp = [], ignores = []; 23 | for (var i=0,l=targets.length; i prev.mtime) { 40 | exec(command, function(err, stdout, stderr) { 41 | if (err) { 42 | console.error(err); 43 | } 44 | if (stdout) { 45 | console.log(stdout); 46 | } 47 | if (stderr) { 48 | console.error(stderr); 49 | } 50 | console.log('[LAST UPDATED]: ' + (new Date())); 51 | }); 52 | } 53 | }); 54 | }); 55 | --------------------------------------------------------------------------------