Repository: jcoglan/fargo Branch: master Commit: 72177b436ca7 Files: 38 Total size: 161.7 KB Directory structure: gitextract_al_6jzo1/ ├── .gitignore ├── .gitmodules ├── Gemfile ├── Jakefile ├── README.markdown ├── bin/ │ └── fargo ├── examples/ │ ├── demo.scm │ ├── fibers.scm │ ├── http.scm │ └── lib-http.js ├── jake.yml ├── source/ │ ├── fargo/ │ │ ├── lib/ │ │ │ ├── primitives.js │ │ │ └── timers.js │ │ ├── runtime/ │ │ │ ├── callable/ │ │ │ │ ├── fiber.js │ │ │ │ ├── macro/ │ │ │ │ │ ├── expansion.js │ │ │ │ │ ├── matches.js │ │ │ │ │ └── tree.js │ │ │ │ ├── macro.js │ │ │ │ ├── procedure.js │ │ │ │ └── syntax.js │ │ │ ├── data/ │ │ │ │ ├── cons.js │ │ │ │ ├── symbol.js │ │ │ │ └── vector.js │ │ │ ├── frame.js │ │ │ ├── scope.js │ │ │ ├── stack.js │ │ │ ├── stackless.js │ │ │ ├── top_level.js │ │ │ └── value.js │ │ ├── scheme.js │ │ ├── scheme.peg │ │ └── scheme_nodes.js │ └── fargo.js ├── test.js └── try-fargo/ ├── analytics.js ├── index.html ├── javascripts/ │ └── packages.js └── style.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ Gemfile.lock build try-fargo/javascripts/fargo try-fargo/downloads ================================================ FILE: .gitmodules ================================================ [submodule "vendor/js.class"] path = vendor/js.class url = git://github.com/jcoglan/js.class.git [submodule "vendor/heist"] path = vendor/heist url = git://github.com/jcoglan/heist.git [submodule "try-fargo/javascripts/jquery-console"] path = try-fargo/javascripts/jquery-console url = git://github.com/chrisdone/jquery-console.git ================================================ FILE: Gemfile ================================================ source :rubygems gem 'jake' ================================================ FILE: Jakefile ================================================ require 'fileutils' jake_hook :build_complete do |build| FileUtils.copy_entry build.source_dir + '/fargo/lib', build.build_dir + '/lib' FileUtils.copy_entry build.source_dir + '/../vendor/js.class/build/min', build.build_dir + '/js.class' FileUtils.cp 'vendor/heist/lib/builtin/syntax.scm', build.build_dir + '/lib/syntax.scm' %w[util logic numeric list vector].each do |lib| FileUtils.cp "vendor/heist/lib/builtin/lib/#{lib}.scm", build.build_dir + "/lib/#{lib}.scm" end FileUtils.copy_entry build.build_dir, build.source_dir + '/../try-fargo/javascripts/fargo' end ================================================ FILE: README.markdown ================================================ # Fargo Try it out at http://fargo.jcoglan.com Fargo is a programming language that runs on Node.js. It's designed to ease asynchronous functional programming by providing features missing in JavaScript, namely tail recursion and some form of continuations. It is still an experiment and a toy. It is loosely based on Scheme, in that I'm using Scheme's function names where appropriate. It is unlikely to become a complete Scheme implementation; at this stage it is an extremely minimal language that you can use where JavaScript is not sufficiently expressive. The initial version was written in various airport and hotel bars. It is probably slow and full of bugs. ## Building Fargo git clone git://github.com/jcoglan/fargo.git cd fargo gem install jake git submodule update --init --recursive cd vendor/js.class jake cd ../../ jake node bin/fargo path/to/program.scm ## Fibers The main reason for Fargo's existence at present is to add fibers to the Node environment to make async programming easier. Fibers are a lightweight form of continuations that allow blocks of code to be suspended and resumed by the user. Many Ruby programmers are using fibers to let them write non-blocking code with blocking-style syntax. In Fargo, fibers look like functions and are callable in the same way. When a fiber is running, you can use the `yield` function which suspends the fiber and returns the yielded value as the result of the fiber's invokation. Next time you call the fiber, it will resume from the last `yield`; the value you invoke the fiber with will become the result of the `yield` expression. Some basic examples: (define stream (fiber (max) (define (loop i) (if (< i max) (begin (yield i) (loop (+ i 1))) 'done)) (loop 0))) ; This binds 2 to `max` and begins running `stream`. The first `yield` is ; called with 0. The next `yield` produces 1, then the fiber exits with `done` (puts (stream 2)) ; -> 0 (puts (stream)) ; -> 1 (puts (stream)) ; -> done (define test (fiber (first) (define second (yield (+ first 2))) second)) ; Binds 10 to `first`, begins the fiber. 12 is yielded (puts (test 10)) ; -> 12 ; The `yield` is replaced with the value 14 and the fiber continues by ; returning the value of `second` (puts (test 14)) ; -> 14 ; The fiber has no more code to run so this produces an error (puts (test 18)) Fibers can help mask async code with callback-free APIs. Here's an example: In Node we can make asynchronous HTTP requests. Let's write a function to expose this facility to Fargo; our function will take a URL and a callback function (a Fargo `Procedure` object, not a JavaScript function) and invoke the callback with the response body after requesting the URL. // lib-http.js Fargo.runtime.define('http-get', function(url, callback) { var uri = require('url').parse(url), client = require('http').createClient(80, uri.hostname); var request = client.request('GET', uri.pathname); request.addListener('response', function(response) { var data = ''; response.addListener('data', function(c) { data += c }); response.addListener('end', function() { callback.exec(data); }); }); return request.end(); }); In Fargo, we can wrap this function in some Fiber yield/resume magic to give us a callback-free version of the function. We can then use this function when running within a fiber to simplify our async code. ; http.scm (load "./lib-http.js") ; This function captures the current fiber and initiates a request. It then ; returns a `yield` as the return value, suspending the fiber. When the ; callback is called, we resume the captured fiber with the response; the ; response is injected at the point of the yield and is returned to the ; caller. (define (fiber-http-get url) (define f (current-fiber)) (http-get url (lambda (response) (f response))) (yield)) ; We wrap our main program in a fiber so it can be suspended at will (define program (fiber () (define page (fiber-http-get "http://www.google.com/")) (puts page))) ; Begins the main program fiber (program) ## Features Fargo's syntax is that of Scheme. Booleans are written as `#t` and `#f`. Strings are be double-quoted only. Numeric literals are base-10 decimals. Lists are delimited with `(` and `)`. Quoted values are prefixed with `'`. The null value is the empty list `'()`. Vectors and characters are currently not implemented. Fargo implements the following syntax elements from Scheme: * `define` for binding variables and creating functions * `begin` for bundling blocks of code as single expressions * `if` for conditional branching * `lambda` for creating first-class anonymous functions * `quote` for defining immutable lists * `and` and `or` for boolean logic The following predicates are included: * `eq?`, `eqv?`, `boolean?`, `number?`, `string?`, `symbol?`, `pair?`, `null?`, `list?`, `procedure?` Binary numeric operators, which delegate to the JavaScript equivalents: * `+`, `-`, `*`, `/`, `>`, `>=`, `<`, `<=`, `=` List primitives and library functions: * `cons`, `car`, `cdr`, `set-car!`, `set-cdr!`, `length`, `map` ## License Copyright (c) 2011 James Coglan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: bin/fargo ================================================ #!/usr/bin/env node var path = require('path'), sys = require('sys'), rl = require('readline'); JSCLASS_PATH = path.dirname(__filename) + '/../build/js.class'; FARGO_PATH = path.dirname(__filename) + '/../build'; require(JSCLASS_PATH + '/loader'); require(JSCLASS_PATH + '/core'); require(JSCLASS_PATH + '/enumerable'); require(path.dirname(__filename) + '/../build/fargo-min'); var runtime = new Fargo.Runtime(), filename = null; if (filename = process.ARGV[2]) { runtime.run(path.resolve(filename)); } else { var readline = rl.createInterface(process.stdin, process.stdout), buffer = ''; var reset = function() { buffer = ''; readline.setPrompt('> '); }; readline.addListener('line', function(line) { buffer += (buffer === '' ? '' : '\n') + line; var parser = new Fargo.SchemeParser(buffer), program = parser.parse(); if (!program) { if (parser.error.actual !== '') { reset(); sys.puts(Fargo.SchemeParser.formatError(parser.error)); } else { readline.setPrompt(' '); } return readline.prompt(); } reset(); try { var result = program.eval(runtime.scope); sys.puts('; => ' + Fargo.stringify(result)); } catch (e) { sys.puts(e); } readline.prompt(); }); readline.addListener('attemptClose', function() { if (buffer.length === 0) { readline.close(); } else { reset(); sys.puts(''); readline.prompt(); } }); readline.prompt(); } ================================================ FILE: examples/demo.scm ================================================ (define factorial (lambda (x) (if (= 0 x) 1 (* (factorial (- x 1)) x)))) (puts (factorial 2000)) (define add (lambda (a) (lambda (b) (+ a b)))) (puts ((add 2) 3)) (puts '(a b c)) (puts (cdr '(a b c))) (define list (cons 1 (cons 2 (cons 3 '())))) (set-car! (cdr list) 5) (puts list) (puts (eq? '(1 2) '(1 2))) (puts (eq? 'foo 'foo)) (puts (eq? '() '())) (puts (list? 'foo)) (define square (lambda (x) (* x x))) (puts (map square '(1 2 3 4))) (puts (let ((x 1) (y 2) (z 3) (h 7)) (+ (+ x y) z))) (puts `(x y ,map)) ================================================ FILE: examples/fibers.scm ================================================ (define stream (fiber (max) (do ((i 0 (+ 1 i))) ((eqv? max i) 'done) (yield i)))) (puts (stream 2)) (puts (stream)) (puts (stream)) (define test (fiber (first) (define second (yield (+ first 2))) second)) (puts (test 10)) (puts (test 14)) (puts (test 18)) ================================================ FILE: examples/http.scm ================================================ (load "./lib-http.js") (define (fiber-http-get url) (http-get url (current-fiber)) (yield)) (define program (fiber () (define page (fiber-http-get "http://www.google.com/")) (puts page))) (program) ================================================ FILE: examples/lib-http.js ================================================ Fargo.runtime.define('http-get', function(url, callback) { var uri = require('url').parse(url), client = require('http').createClient(80, uri.hostname); var request = client.request('GET', uri.pathname); request.addListener('response', function(response) { var data = ''; response.addListener('data', function(c) { data += c }); response.addListener('end', function() { callback.exec(data); }); }); return request.end(); }); ================================================ FILE: jake.yml ================================================ --- source_directory: source build_directory: build layout: together builds: src: suffix: false packer: false min: shrink_vars: true private: true packages: fargo: - fargo - fargo/scheme - fargo/scheme_nodes - fargo/runtime/data/cons - fargo/runtime/data/symbol - fargo/runtime/data/vector - fargo/runtime/callable/procedure - fargo/runtime/callable/syntax - fargo/runtime/callable/macro - fargo/runtime/callable/macro/matches - fargo/runtime/callable/macro/tree - fargo/runtime/callable/macro/expansion - fargo/runtime/callable/fiber - fargo/runtime/stack - fargo/runtime/stackless - fargo/runtime/frame - fargo/runtime/scope - fargo/runtime/top_level - fargo/runtime/value ================================================ FILE: source/fargo/lib/primitives.js ================================================ var Runtime = Fargo.Runtime, Cons = Runtime.Cons, Symbol = Runtime.Symbol, NULL = Cons.NULL; //================================================================ // Core syntax Fargo.runtime.syntax('define', function(scope, cells) { if (cells.car.klass === Cons) { var name = cells.car.car.name, params = cells.car.cdr, body = cells.cdr, proc = new Runtime.Procedure(scope, params, body); scope.define(name, proc); return proc; } else if (cells.car.klass === Symbol) { var value = Fargo.evaluate(cells.cdr.car, scope); scope.define(cells.car.name, value); return value; } }); Fargo.runtime.syntax('set!', function(scope, cells) { return scope.set(cells.car.name, Fargo.evaluate(cells.cdr.car, scope)); }); Fargo.runtime.syntax('if', function(scope, cells) { var which = (Fargo.evaluate(cells.car, scope) === false) ? cells.cdr.cdr.car : cells.cdr.car; if (which === undefined) return false; else return new Runtime.Frame(which, scope); }); Fargo.runtime.syntax('begin', function(scope, cells) { return new Runtime.Body(cells, scope); }); Fargo.runtime.syntax('lambda', function(scope, cells) { return new Runtime.Procedure(scope, cells.car, cells.cdr); }); Fargo.runtime.syntax('quote', function(scope, cells) { return Fargo.freeze(cells.car); }); Fargo.runtime.syntax('define-syntax', function(scope, cells) { var macro = Fargo.evaluate(cells.cdr.car, scope); scope.define(cells.car.name, macro); return macro; }); Fargo.runtime.syntax('syntax-rules', function(scope, cells) { return new Runtime.Macro(scope, cells.car, cells.cdr); }); //================================================================ // Fibers Fargo.runtime.syntax('fiber', function(scope, cells) { return new Runtime.Fiber(scope, cells.car, cells.cdr); }); Fargo.runtime.syntax('current-fiber', function(scope, cells) { return scope.runtime.currentFiber; }); Fargo.runtime.define('yield', function(value) { value = (value === undefined) ? NULL : value; return {yieldValue: value}; }); Fargo.runtime.define('call-with-current-continuation', function() { return NULL; }); //================================================================ // I/O Fargo.runtime.syntax('load', function(scope, cells) { scope.run(Fargo.evaluate(cells.car, scope)); return true; }); Fargo.runtime.define('puts', function(string) { Fargo.puts(string); return string; }); Fargo.runtime.define('exit', function() { process.exit(); }); //================================================================ // Predicates var eqv = function(a,b) { if (a.klass === Symbol && b.klass === Symbol) return a.name === b.name; else return a === b; }; Fargo.runtime.define('eqv?', eqv); Fargo.runtime.define('eq?', eqv); Fargo.runtime.define('equal?', function(a, b) { return (a && a.equals) ? a.equals(b) : a === b; }); Fargo.runtime.define('pair?', function(object) { return object.klass === Cons && object !== NULL; }); Fargo.runtime.define('vector?', function(object) { return object.klass === Runtime.Vector; }); Fargo.runtime.define('complex?', function(object) { return typeof object === 'number' }); Fargo.runtime.define('string?', function(object) { return typeof object === 'string' }); Fargo.runtime.define('symbol?', function(object) { return object.klass === Runtime.Symbol; }); Fargo.runtime.define('procedure?', function(object) { return object.klass === Runtime.Function; }); //================================================================ // Math library Fargo.runtime.define('+', function() { var value = arguments[0]; if (value === undefined) value = 0; for (var i = 1, n = arguments.length; i < n; i++) value += arguments[i]; return value; }); Fargo.runtime.define('-', function() { var value = arguments[0]; if (arguments.length === 1) return 0 - value; for (var i = 1, n = arguments.length; i < n; i++) value -= arguments[i]; return value; }); Fargo.runtime.define('*', function() { var value = arguments[0]; if (value === undefined) value = 1; for (var i = 1, n = arguments.length; i < n; i++) value *= arguments[i]; return value; }); Fargo.runtime.define('/', function() { var value = arguments[0]; if (arguments.length === 1) return 1/value; for (var i = 1, n = arguments.length; i < n; i++) value /= arguments[i]; return value; }); Fargo.runtime.define('<', function(a,b) { return a < b }); Fargo.runtime.define('<=', function(a,b) { return a <= b }); Fargo.runtime.define('>', function(a,b) { return a > b }); Fargo.runtime.define('>=', function(a,b) { return a >= b }); 'ceil floor round sin cos tan asin acos atan exp log sqrt random'. split(' ').forEach(function(fn) { Fargo.runtime.define(fn, Math[fn]); }); Fargo.runtime.define('expt', Math.pow); Fargo.runtime.define('number->string', function(number) { return number.toString(10); }); Fargo.runtime.define('string->number', function(string) { return parseFloat(string, 10); }); Fargo.runtime.define('PI', Math.PI); //================================================================ // Lists and pairs Fargo.runtime.define('cons', function(a,b) { return new Cons(a,b) }); Fargo.runtime.define('car', function(pair) { return pair.car }); Fargo.runtime.define('cdr', function(pair) { return pair.cdr }); Fargo.runtime.define('set-car!', function(pair, value) { if (pair.frozen) throw new Error('Cannot set-car! on immutable list'); pair.car = value; return value; }); Fargo.runtime.define('set-cdr!', function(pair, value) { if (pair.frozen) throw new Error('Cannot set-cdr! on immutable list'); pair.cdr = value; return value; }); Fargo.runtime.define('caar', function(pair) { return pair.car.car }); Fargo.runtime.define('cadr', function(pair) { return pair.cdr.car }); Fargo.runtime.define('cdar', function(pair) { return pair.car.cdr }); Fargo.runtime.define('cddr', function(pair) { return pair.cdr.cdr }); Fargo.runtime.define('caaar', function(pair) { return pair.car.car.car }); Fargo.runtime.define('caadr', function(pair) { return pair.cdr.car.car }); Fargo.runtime.define('cadar', function(pair) { return pair.car.cdr.car }); Fargo.runtime.define('caddr', function(pair) { return pair.cdr.cdr.car }); Fargo.runtime.define('cdaar', function(pair) { return pair.car.car.cdr }); Fargo.runtime.define('cdadr', function(pair) { return pair.cdr.car.cdr }); Fargo.runtime.define('cddar', function(pair) { return pair.car.cdr.cdr }); Fargo.runtime.define('cdddr', function(pair) { return pair.cdr.cdr.cdr }); Fargo.runtime.define('caaaar', function(pair) { return pair.car.car.car.car }); Fargo.runtime.define('caaadr', function(pair) { return pair.cdr.car.car.car }); Fargo.runtime.define('caadar', function(pair) { return pair.car.cdr.car.car }); Fargo.runtime.define('caaddr', function(pair) { return pair.cdr.cdr.car.car }); Fargo.runtime.define('cadaar', function(pair) { return pair.car.car.cdr.car }); Fargo.runtime.define('cadadr', function(pair) { return pair.cdr.car.cdr.car }); Fargo.runtime.define('caddar', function(pair) { return pair.car.cdr.cdr.car }); Fargo.runtime.define('cadddr', function(pair) { return pair.cdr.cdr.cdr.car }); Fargo.runtime.define('cdaaar', function(pair) { return pair.car.car.car.cdr }); Fargo.runtime.define('cdaadr', function(pair) { return pair.cdr.car.car.cdr }); Fargo.runtime.define('cdadar', function(pair) { return pair.car.cdr.car.cdr }); Fargo.runtime.define('cdaddr', function(pair) { return pair.cdr.cdr.car.cdr }); Fargo.runtime.define('cddaar', function(pair) { return pair.car.car.cdr.cdr }); Fargo.runtime.define('cddadr', function(pair) { return pair.cdr.car.cdr.cdr }); Fargo.runtime.define('cdddar', function(pair) { return pair.car.cdr.cdr.cdr }); Fargo.runtime.define('cddddr', function(pair) { return pair.cdr.cdr.cdr.cdr }); Fargo.runtime.define('apply', function(procedure, list) { return procedure.apply(list.toArray()); }); //================================================================ // Vectors Fargo.runtime.define('make-vector', function(size, fill) { if (fill === undefined) fill = NULL; var elements = []; while (size--) elements.push(fill); return new Runtime.Vector(elements); }); Fargo.runtime.define('vector-length', function(vector) { return vector.members.length; }); Fargo.runtime.define('vector-ref', function(vector, k) { var size = vector.members.length; if (k < 0 || k >= size) throw new Error('Index out of bounds'); return vector.members[k]; }); Fargo.runtime.define('vector-set!', function(vector, k, object) { var size = vector.members.length; if (k < 0 || k >= size) throw new Error('Index out of bounds'); if (vector.frozen) throw new Error('Cannot vector-set! on immutable vector'); return vector.members[k] = object; }); ================================================ FILE: source/fargo/lib/timers.js ================================================ Fargo.runtime.define('set-timeout', function(procedure, millis) { return setTimeout(function() { procedure.exec() }, millis); }); Fargo.runtime.define('clear-timeout', function(id) { clearTimeout(id); return id; }); Fargo.runtime.define('set-interval', function(procedure, millis) { return setInterval(function() { procedure.exec() }, millis); }); Fargo.runtime.define('clear-interval', function(id) { clearInterval(id); return id; }); ================================================ FILE: source/fargo/runtime/callable/fiber.js ================================================ Fargo.Runtime.extend({ Fiber: new JS.Class(Fargo.Runtime.Procedure, { apply: function(args) { var R = Fargo.Runtime, NULL = R.Cons.NULL; if (!this._stack) { this._scope = this._createScope(args); this._stack = new R.Stack(new R.Body(this._body, this._scope)); } var runtime = this._scope.runtime, fiber = runtime.currentFiber, stack = runtime.stack; runtime.currentFiber = this; runtime.stack = this._stack; var arg = (args[0] === undefined) ? NULL : args[0], value = runtime.stack.resume(arg); runtime.currentFiber = fiber; runtime.stack = stack; return value; } }) }); ================================================ FILE: source/fargo/runtime/callable/macro/expansion.js ================================================ Fargo.Runtime.Macro.extend({ Expansion: new JS.Class({ initialize: function(lexicalScope, callingScope, template, matches) { this._lexicalScope = lexicalScope; this._callingScope = callingScope; this.expression = this.expand(template, matches); }, expand: function(template, matches, depth, ignoringEllipses) { var klass = (template && template.klass), depth = depth || 0, Cons = Fargo.Runtime.Cons, NULL = Cons.NULL, ELLIPSIS = Fargo.Runtime.Macro.ELLIPSIS, result, last, repeater, templatePair, push, cell, followedByEllipsis, dx; if (klass === Cons) { if (template === NULL) return NULL; if (ELLIPSIS.equals(template.car)) return this.expand(template.cdr.car, matches, depth, true); templatePair = template; push = function(value) { var pair = new Cons(value); result = result || pair; if (last) last.cdr = pair; last = pair; }; while (templatePair.klass === Cons && templatePair !== NULL) { cell = templatePair.car; followedByEllipsis = (templatePair.cdr.klass === Cons && ELLIPSIS.equals(templatePair.cdr.car) && !ignoringEllipses); dx = followedByEllipsis ? 1 : 0; if (followedByEllipsis) repeater = cell; if (ELLIPSIS.equals(cell) && !ignoringEllipses) { matches.expand(repeater, depth + 1, function() { push(this.expand(repeater, matches, depth + 1)); }, this); } else if (!followedByEllipsis) { push(this.expand(cell, matches, depth + dx, ignoringEllipses)); } templatePair = templatePair.cdr; } if (last) last.cdr = this.expand(templatePair, matches, depth, ignoringEllipses); return result; } else if (klass === Fargo.Runtime.Vector) { result = []; push = function(value) { result.push(value) }; var elements = template.members; for (var i = 0, n = elements.length; i < n; i++) { cell = elements[i]; followedByEllipsis = (ELLIPSIS.equals(template.get(i + 1)) && !ignoringEllipses); dx = followedByEllipsis ? 1 : 0; if (followedByEllipsis) repeater = cell; if (ELLIPSIS.equals(cell) && !ignoringEllipses) { matches.expand(repeater, depth + 1, function() { push(this.expand(repeater, matches, depth + 1)); }, this); } else if (!followedByEllipsis) { push(this.expand(cell, matches, depth + dx, ignoringEllipses)); } } return new Fargo.Runtime.Vector(result); } else if (klass === Fargo.Runtime.Symbol) { if (matches.has(template.name)) return matches.get(template.name); else return new Fargo.Runtime.Symbol(template.name); } else return template; } }) }); ================================================ FILE: source/fargo/runtime/callable/macro/matches.js ================================================ Fargo.Runtime.Macro.extend({ Matches: new JS.Class({ initialize: function(pattern, formals) { this._data = {}; var names = Fargo.Runtime.Macro.patternVars(pattern, formals), i = names.length; while (i--) this._data[names[i]] = new Fargo.Runtime.Macro.Tree(names[i]); }, descend: function(names, depth) { for (var name in this._data) { if (names.indexOf(name) >= 0) this._data[name].descend(depth); } }, put: function(name, value) { if (this._data.hasOwnProperty(name)) this._data[name].push(value); }, has: function(name) { return this._data.hasOwnProperty(name); }, get: function(name) { return this._data[name].read(); }, expand: function(template, depth, callback, context) { var names = Fargo.Runtime.Macro.patternVars(template), i = this._size(names, depth); while (i--) { callback.call(context); this._iterate(names, depth); } }, _size: function(names, depth) { var sizes = [], size; for (var name in this._data) { size = this._data[name].size(depth); if (names.indexOf(name) >= 0 && size !== null && sizes.indexOf(size) < 0) sizes.push(size); } if (sizes.length === 1) return sizes[0]; else throw new Error('Mismatched repetition patterns'); }, _iterate: function(names, depth) { for (var name in this._data) { if (names.indexOf(name) >= 0) this._data[name].shift(depth); } } }) }); ================================================ FILE: source/fargo/runtime/callable/macro/tree.js ================================================ Fargo.Runtime.Macro.extend({ Tree: new JS.Class({ initialize: function(name) { this._name = name; this._data = []; this._depth = 0; }, descend: function(depth) { this._tail(depth-1).push([]); this._depth = Math.max(this._depth, depth); }, push: function(value) { this._tail(this._depth).push(value); }, read: function() { var indexes = this._indexes(), depth = this._depth; return this._current(depth)[indexes[depth]]; }, shift: function(depth) { if (depth > this._depth) return; var indexes = this._indexes(); indexes[depth] += 1; if (indexes[depth] >= this._current(depth).length) indexes[depth] = 0; }, size: function(depth) { if (depth > this._depth) return null; return this._current(depth).length; }, _tail: function(depth) { var list = this._data; while (depth--) list = list[list.length - 1]; return list; }, _current: function(depth) { var list = this._data, idx = this._indexes(); for (var i = 0; i < depth; i++) list = list[idx[i]]; return list; }, _indexes: function() { if (this._idx) return this._idx; this._idx = []; for (var i = 0, n = this._depth; i <= n; i++) this._idx.push(0); return this._idx; } }) }); ================================================ FILE: source/fargo/runtime/callable/macro.js ================================================ Fargo.Runtime.extend({ Macro: new JS.Class(Fargo.Runtime.Procedure, { extend: { ELLIPSIS: new Fargo.Runtime.Symbol('...'), RESERVED: ['_', '...'], patternVars: function(pattern, excluded, results) { excluded = excluded || []; results = results || []; if (pattern === Fargo.Runtime.Cons.NULL) return results; var klass = (pattern && pattern.klass), Cons = Fargo.Runtime.Cons, NULL = Cons.NULL, name, cell, elements, i; if (klass === Fargo.Runtime.Symbol) { name = pattern.name; if (excluded.indexOf(name) >= 0 || this.RESERVED.indexOf(name) >= 0) return; if (results.indexOf(name) < 0) results.push(name); } if (klass === Cons) { cell = pattern; while (cell.klass === Cons && cell !== NULL) { this.patternVars(cell.car, excluded, results); cell = cell.cdr; } this.patternVars(cell, excluded, results); } if (klass === Fargo.Runtime.Vector) { elements = pattern.members; i = elements.length; while (i--) this.patternVars(elements[i], excluded, results); } return results; } }, initialize: function() { this.callSuper(); this._params = this._params.map(function(s) { return s.name }); }, call: function(scope, cells) { var result = this.ruleFor(cells, scope); if (!result) throw new Error('Syntax error'); return new this.klass.Expansion(this._lexicalScope, scope, result[0].car.cdr.car, result[1]); }, ruleFor: function(cells, scope) { var rule = this._body, Cons = Fargo.Runtime.Cons, NULL = Cons.NULL; while (rule !== NULL) { var matches = this.ruleMatches(scope, rule.car.car.cdr, cells); if (matches) return [rule, matches]; rule = rule.cdr; } }, ruleMatches: function(scope, pattern, input, matches, depth) { matches = matches || new this.klass.Matches(pattern, this._params); depth = depth || 0; var klass = (pattern && pattern.klass), Cons = Fargo.Runtime.Cons, NULL = Cons.NULL, self = this, patternPair, inputPair, token, followedByEllipsis, dx, consume, consumed, inputIndex; if (klass === Cons) { if (pattern === NULL) return (input === NULL) ? matches : null; if (!input || input.klass !== Cons) return null; patternPair = pattern, inputPair = input; while (patternPair.klass === Cons && patternPair !== NULL) { token = patternPair.car; if (this.klass.ELLIPSIS.equals(token)) { patternPair = patternPair.cdr; continue; } followedByEllipsis = this.klass.ELLIPSIS.equals(patternPair.cdr.car); dx = followedByEllipsis ? 1 : 0; if (followedByEllipsis) matches.descend(this.klass.patternVars(token, this._params), depth + dx); consume = function() { return (inputPair.klass === Cons && inputPair !== NULL) ? self.ruleMatches(scope, token, inputPair.car, matches, depth + dx) : null; }; consumed = consume(); if (!consumed && !followedByEllipsis) return null; if (consumed) inputPair = inputPair.cdr; while (followedByEllipsis && consume()) inputPair = inputPair.cdr; patternPair = patternPair.cdr; } if (!this.ruleMatches(scope, patternPair, inputPair, matches, depth)) return null; } else if (klass === Fargo.Runtime.Vector) { if (!input || input.klass !== Fargo.Runtime.Vector) return null; inputIndex = 0; var elements = pattern.members; for (var i = 0, n = elements.length; i < n; i++) { token = elements[i]; if (this.klass.ELLIPSIS.equals(token)) continue; followedByEllipsis = this.klass.ELLIPSIS.equals(pattern.get(i + 1)); dx = followedByEllipsis ? 1 : 0; if (followedByEllipsis) matches.descend(this.klass.patternVars(token, this._params), depth + dx); consume = function() { return input.get(inputIndex) !== undefined && self.ruleMatches(scope, token, input.get(inputIndex), matches, depth + dx); }; consumed = consume(); if (!consumed && !followedByEllipsis) return null; if (consumed) inputIndex += 1; while (followedByEllipsis && consume()) inputIndex += 1; } if (inputIndex !== input.length) return null; } else if (klass === Fargo.Runtime.Symbol) { if (this._params.indexOf(pattern.name) >= 0) return pattern.equals(input) && this._lexicalScope.innermostBinding(pattern.name) === scope.innermostBinding(input.name); else matches.put(pattern.name, input); } else { if (pattern !== input) return null; } return matches; } }) }); ================================================ FILE: source/fargo/runtime/callable/procedure.js ================================================ Fargo.Runtime.extend({ Procedure: new JS.Class({ initialize: function(scope, params, body) { this._lexicalScope = scope; this._runtime = scope.runtime; if (typeof params === 'function') { this._body = params; } else { this._params = params; this._body = body; } }, call: function(scope, cells) { var args = [], cell = cells, NULL = Fargo.Runtime.Cons.NULL; while (cell !== NULL) { args.push(Fargo.evaluate(cell.car, scope)); cell = cell.cdr; } return this.apply(args); }, apply: function(args) { var NULL = Fargo.Runtime.Cons.NULL; if (typeof this._body === 'function') return this._body.apply(this, args); var scope = this._createScope(args); return new Fargo.Runtime.Body(this._body, scope); }, exec: function() { var args = [].slice.call(arguments); var frame = this.apply(args); return this._runtime.stack.push(frame); }, toString: function() { var name = this.name ? ':' + this.name : ''; return '#'; }, _createScope: function(args) { var Cons = Fargo.Runtime.Cons, NULL = Cons.NULL, param = this._params, scope = this._lexicalScope.spawn(), i = 0; while (param.klass === Cons && param !== NULL) { scope.define(param.car.name, args[i]); param = param.cdr; i += 1; } if (param !== NULL) scope.define(param.name, Cons.list(args.slice(i))); return scope; } }) }); ================================================ FILE: source/fargo/runtime/callable/syntax.js ================================================ Fargo.Runtime.extend({ Syntax: new JS.Class(Fargo.Runtime.Procedure, { call: function(scope, cells) { return this._body.call(this, scope, cells); } }) }); ================================================ FILE: source/fargo/runtime/data/cons.js ================================================ Fargo.Runtime.extend({ Cons: new JS.Class({ include: JS.Enumerable, initialize: function(car, cdr) { this.car = (car === undefined) ? this.klass.NULL : car; this.cdr = (cdr === undefined) ? this.klass.NULL : cdr; if (this.car !== this.klass.NULL) this.car.parent = this; }, forEach: function(block, context) { var pair = this; while (pair.klass === this.klass && pair !== this.klass.NULL) { block.call(context, pair.car); pair = pair.cdr; } }, clone: function() { return this.klass.list(this); }, equals: function(other) { if (!other || other.klass !== this.klass) return false; var E = JS.Enumerable; return E.areEqual(this.car, other.car) && E.areEqual(this.cdr, other.cdr); }, eval: function(scope) { var frame = new Fargo.Runtime.Frame(this, scope); return scope.runtime.stack.push(frame); }, freeze: function() { if (this.frozen) return; this.frozen = true; Fargo.freeze(this.car); Fargo.freeze(this.cdr); }, toString: function() { var elems = [], pair = this, NULL = this.klass.NULL; while (pair.klass === this.klass && pair !== NULL) { elems.push(Fargo.stringify(pair.car)); pair = pair.cdr; } var tail = (pair === NULL) ? '' : ' . ' + pair; return '(' + elems.join(' ') + tail + ')'; } }) }); Fargo.Runtime.Cons.extend({ list: function(array, tail) { var list, tail, i; if (array.klass === this) { list = tail = new this(); while (array !== this.NULL) { tail.car = array.car; tail = tail.cdr = (array.cdr === this.NULL) ? this.NULL : new this(); array = array.cdr; } } else { list = tail || this.NULL; i = array.length; while (i--) list = new this(array[i], list); } return list; }, NULL: new Fargo.Runtime.Cons() }); (function() { var nil = Fargo.Runtime.Cons.NULL; nil.extend({ car: undefined, cdr: undefined, equals: function(other) { return other === this }, toString: function() { return '()' } }); })(); ================================================ FILE: source/fargo/runtime/data/symbol.js ================================================ Fargo.Runtime.extend({ Symbol: new JS.Class({ initialize: function(name) { this.name = name; }, equals: function(other) { return other && other.klass === this.klass && other.name === this.name; }, eval: function(scope) { return scope.resolve(this.name); }, toString: function() { return this.name; } }) }); ================================================ FILE: source/fargo/runtime/data/vector.js ================================================ Fargo.Runtime.extend({ Vector: new JS.Class({ include: JS.Enumerable, initialize: function(elements) { this.members = elements.slice(); this.length = elements.length; }, forEach: function(block, context) { for (var i = 0, n = this.members.length; i < n; i++) block.call(context, this.members[i]); }, equals: function(other) { if (!other || other.klass !== this.klass) return false; if (other.length !== this.length) return false; var i = this.length; while (i--) { if (!JS.Enumerable.areEqual(this.members[i], other.members[i])) return false; } return true; }, get: function(index) { return this.members[index]; }, clone: function() { return new this.klass(this.members); }, eval: function(scope) { return this.clone(); }, freeze: function() { if (this.frozen) return; this.frozen = true; var el = this.members, i = el.length; while (i--) Fargo.freeze(el[i]); }, toString: function() { var elems = []; for (var i = 0, n = this.members.length; i < n; i++) elems.push(Fargo.stringify(this.members[i])); return '#(' + elems.join(' ') + ')'; } }) }); ================================================ FILE: source/fargo/runtime/frame.js ================================================ Fargo.Runtime.extend({ Frame: new JS.Class({ initialize: function(expression, scope) { this._reset(expression); this._scope = scope; }, process: function() { var expr = this._expression, scope = this._scope, Runtime = Fargo.Runtime, Cons = Runtime.Cons, NULL = Cons.NULL; if (!expr || expr.klass !== Cons) { this.complete = true; return Fargo.evaluate(expr, scope); } var proc = this._values.car; if (proc.klass === Runtime.Syntax || proc.klass === Runtime.Macro || this._current === NULL) { if (typeof proc.call !== 'function') throw new Error('Invalid expression: ' + this._expression); this.complete = true; var result = proc.call(scope, this._values.cdr); if (result === null || result === undefined) throw new Error('Expression returned no value: ' + expression); return (result && result.klass === Fargo.Runtime.Macro.Expansion) ? this._reset(result.expression, true) : result; } var stack = scope.runtime.stack, current = this._current, value = this._curValue; var result = stack.push(new Runtime.Frame(current.car, scope)); this._curValue.car = result; this._current = this._current.cdr; this._curValue = this._curValue.cdr; return result; }, fill: function(frame, result) { var subexpr = frame.target, expr = this._expression, value = this._values, NULL = Fargo.Runtime.Cons.NULL; while (expr.car !== subexpr && expr !== NULL) { expr = expr.cdr; value = value.cdr; } if (expr !== NULL) value.car = new Fargo.Runtime.Value(result); }, _reset: function(expression, replace) { if (replace) { this._expression.parent.car = expression; expression.parent = this._expression.parent; } this._expression = expression; this.target = expression; this._current = expression; this._values = Fargo.clone(expression); this._curValue = this._values; this.complete = false; } }) }); Fargo.Runtime.extend({ Body: new JS.Class(Fargo.Runtime.Frame, { initialize: function(expressions, scope) { this._expression = expressions; this._scope = scope; this._values = []; }, process: function() { var expression = this._expression.car, Frame = Fargo.Runtime.Frame, NULL = Fargo.Runtime.Cons.NULL; this._expression = this._expression.cdr; if (this._expression === NULL) { this.complete = true; return new Frame(expression, this._scope); } var stack = this._scope.runtime.stack; return stack.push(new Frame(expression, this._scope)); }, fill: function() {} }) }); ================================================ FILE: source/fargo/runtime/scope.js ================================================ Fargo.Runtime.extend({ Scope: new JS.Class({ initialize: function(runtime, parent) { this.runtime = runtime; this._parent = parent; this._vars = {}; }, spawn: function() { return new Fargo.Runtime.Scope(this.runtime, this); }, set: function(name, value) { var scope = this.innermostBinding(name); if (!scope) throw new Error('Undefined variable ' + name); return scope._vars[name] = value; }, resolve: function(name) { var value, scope = this; while (value === undefined && scope) { value = scope._vars[name]; scope = scope._parent; } if (value !== undefined) return value; throw new Error('Undefined variable ' + name); }, innermostBinding: function(name) { var scope = this; while (scope && !scope._vars.hasOwnProperty(name)) scope = scope._parent; return scope; }, define: function(name, value) { if (typeof value === 'function') value = new Fargo.Runtime.Procedure(this, value); if (!value.name) value.name = name; return this._vars[name] = value; }, syntax: function(name, block) { var syntax = new Fargo.Runtime.Syntax(this, block); syntax.name = name; return this._vars[name] = syntax; }, run: function(pathname) { var dirname = this._path ? Fargo.dirname(this._path) : '', fqpath = Fargo.path(dirname, pathname), runtime = Fargo.runtime, scope = new Fargo.Runtime.FileScope(fqpath, this.runtime, this); Fargo.runtime = this.runtime; if (!/\.[^\.\/]+$/.test(fqpath)) fqpath += '.scm'; if (/\.js$/i.test(fqpath)) { Fargo.loadJavaScript(fqpath); } else { var source = Fargo.readFile(fqpath), parser = new Fargo.SchemeParser(source), program = parser.parse(); if (program) program.eval(scope); else throw new Error(Fargo.SchemeParser.formatError(parser.error)); } Fargo.runtime = runtime; } }) }); Fargo.Runtime.extend({ FileScope: new JS.Class(Fargo.Runtime.Scope, { initialize: function(path, runtime, parent) { this._path = path; this.runtime = runtime; this._parent = parent; this._vars = parent._vars; } }) }); ================================================ FILE: source/fargo/runtime/stack.js ================================================ Fargo.Runtime.extend({ Stack: new JS.Class({ initialize: function(frame) { this._frames = []; if (frame) this._frames.push(frame); }, resume: function(value) { var frames = this._frames, last; if (frames.length === 0) throw new Error('Dead fiber called'); if (this._yield) { last = frames.pop(); frames[frames.length - 1].fill(last, value); delete this._yield; } this.clear(); return this._yield ? this._value.yieldValue : this._value; }, push: function(frame) { var frames = this._frames; frames.push(frame); this.clear(frames.length - 1); return this._value; }, clear: function(limit) { var frames = this._frames, limit = limit || 0; while (frames.length > limit && !this._yield) this.process(); }, process: function() { var frames = this._frames, Frame = Fargo.Runtime.Frame, last = frames[frames.length - 1], value = last.process(), klass = value && value.klass; this.setValue(value); if (this._yield || frames.length === 0 || !last.complete) return; if (this._tail) this._value.target = last.target; frames.pop(); if (klass && (klass === Frame || klass.superclass === Frame)) this._frames.push(value); }, setValue: function(value) { var Frame = Fargo.Runtime.Frame; this._value = value; this._yield = value && value.yieldValue !== undefined; this._tail = value && value.klass && (value.klass === Frame || value.klass.superclass === Frame); } }) }); ================================================ FILE: source/fargo/runtime/stackless.js ================================================ Fargo.Runtime.extend({ Stackless: new JS.Class({ push: function(frame) { this._current = frame; var Frame = Fargo.Runtime.Frame, klass = this._current.klass; while (klass && (klass === Frame || klass.superclass === Frame)) { this._current = this.process(); klass = (this._current || {}).klass; } return this._current; }, process: function() { var expression = this._current._expression, scope = this._current._scope, NULL = Fargo.Runtime.Cons.NULL; if (this._current.klass === Fargo.Runtime.Body) { while (expression.cdr !== NULL) { Fargo.evaluate(expression.car, scope); expression = expression.cdr; } return new Fargo.Runtime.Frame(expression.car, scope); } if (expression.klass !== Fargo.Runtime.Cons) return Fargo.evaluate(expression, scope); var proc = (expression !== NULL) && Fargo.evaluate(expression.car, scope); if (typeof proc.call !== 'function') throw new Error('Invalid expression: ' + expression); var result = proc.call(scope, expression.cdr); if (result === null || result === undefined) throw new Error('Expression has no value: ' + expression); if (!result || result.klass !== Fargo.Runtime.Macro.Expansion) return result; expression.parent.car = result.expression; result.expression.parent = expression.parent; return new Fargo.Runtime.Frame(result.expression, scope); } }) }); ================================================ FILE: source/fargo/runtime/top_level.js ================================================ Fargo.Runtime.extend({ TopLevel: new JS.Class(Fargo.Runtime.Scope, { initialize: function() { this.callSuper(); this.runtime.scope = this; // Built-in functions and syntax this.run(FARGO_PATH + '/lib/primitives.js'); this.run(FARGO_PATH + '/lib/syntax.scm'); // Core Scheme libraries this.run(FARGO_PATH + '/lib/util.scm'); this.run(FARGO_PATH + '/lib/logic.scm'); this.run(FARGO_PATH + '/lib/numeric.scm'); this.run(FARGO_PATH + '/lib/list.scm'); this.run(FARGO_PATH + '/lib/vector.scm'); // Fargo platform libraries this.run(FARGO_PATH + '/lib/timers.js'); } }) }); ================================================ FILE: source/fargo/runtime/value.js ================================================ Fargo.Runtime.extend({ Value: new JS.Class({ initialize: function(value) { this.value = value; } }) }); ================================================ FILE: source/fargo/scheme.js ================================================ (function() {; var namespace = this; namespace = namespace.Fargo = namespace.Fargo || {}; if (typeof exports === "object") { exports.Fargo = this.Fargo; } })(); Fargo.Scheme = new JS.Module("Fargo.Scheme", { root: "program", __consume__program: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.program = this._nodeCache.program || {}; var cached = this._nodeCache.program[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var index2 = this._offset; address1 = this.__consume__shebang(); if (address1) { } else { this._offset = index2; var klass0 = this.klass.SyntaxNode; address1 = new klass0("", this._offset, []); this._offset += 0; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var remaining0 = 0; var index3 = this._offset; var elements1 = []; var text1 = ""; var address3 = true; while (address3) { address3 = this.__consume__cell(); if (address3) { elements1.push(address3); text1 += address3.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index3; var klass1 = this.klass.SyntaxNode; address2 = new klass1(text1, this._offset, elements1); this._offset += text1.length; } else { address2 = null; } if (address2) { elements0.push(address2); text0 += address2.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass2 = null; if (Fargo.Scheme.Program instanceof Function) { klass2 = Fargo.Scheme.Program; } else { klass2 = this.klass.SyntaxNode; } address0 = new klass2(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.Program instanceof Function)) { address0.extend(Fargo.Scheme.Program); } this._offset += text0.length; } else { address0 = null; } return this._nodeCache.program[index0] = address0; }, __consume__shebang: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.shebang = this._nodeCache.shebang || {}; var cached = this._nodeCache.shebang[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var remaining0 = 0; var index2 = this._offset; var elements1 = []; var text1 = ""; var address2 = true; while (address2) { address2 = this.__consume__space(); if (address2) { elements1.push(address2); text1 += address2.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index2; var klass0 = this.klass.SyntaxNode; address1 = new klass0(text1, this._offset, elements1); this._offset += text1.length; } else { address1 = null; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address3 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 2); } else { slice0 = null; } if (slice0 === "#!") { var klass1 = this.klass.SyntaxNode; address3 = new klass1("#!", this._offset, []); this._offset += 2; } else { address3 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address3) { elements0.push(address3); text0 += address3.textValue; var address4 = null; var remaining1 = 0; var index3 = this._offset; var elements2 = []; var text2 = ""; var address5 = true; while (address5) { var index4 = this._offset; var elements3 = []; var labelled1 = {}; var text3 = ""; var address6 = null; var index5 = this._offset; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } var temp0 = slice2; var match0 = null; if (match0 = temp0 && temp0.match(/^[\n\r]/)) { var klass2 = this.klass.SyntaxNode; address6 = new klass2(match0[0], this._offset, []); this._offset += 1; } else { address6 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[\n\r]", actual: slice3 || ""}; } } this._offset = index5; if (!(address6)) { var klass3 = this.klass.SyntaxNode; address6 = new klass3("", this._offset, []); this._offset += 0; } else { address6 = null; } if (address6) { elements3.push(address6); text3 += address6.textValue; var address7 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } var temp1 = slice4; if (temp1 === null) { address7 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } else { var klass4 = this.klass.SyntaxNode; address7 = new klass4(temp1, this._offset, []); this._offset += 1; } if (address7) { elements3.push(address7); text3 += address7.textValue; } else { elements3 = null; this._offset = index4; } } else { elements3 = null; this._offset = index4; } if (elements3) { this._offset = index4; var klass5 = this.klass.SyntaxNode; address5 = new klass5(text3, this._offset, elements3, labelled1); this._offset += text3.length; } else { address5 = null; } if (address5) { elements2.push(address5); text2 += address5.textValue; remaining1 -= 1; } } if (remaining1 <= 0) { this._offset = index3; var klass6 = this.klass.SyntaxNode; address4 = new klass6(text2, this._offset, elements2); this._offset += text2.length; } else { address4 = null; } if (address4) { elements0.push(address4); text0 += address4.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass7 = this.klass.SyntaxNode; address0 = new klass7(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } return this._nodeCache.shebang[index0] = address0; }, __consume__cell: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.cell = this._nodeCache.cell || {}; var cached = this._nodeCache.cell[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var index2 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; address1 = this.__consume__ignore(); if (address1) { elements0.push(address1); text0 += address1.textValue; labelled0.ignore = address1; var address2 = null; address2 = this.__consume__quote(); if (address2) { elements0.push(address2); text0 += address2.textValue; labelled0.quote = address2; var address3 = null; address3 = this.__consume__cell(); if (address3) { elements0.push(address3); text0 += address3.textValue; labelled0.cell = address3; } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } if (elements0) { this._offset = index2; var klass0 = null; if (Fargo.Scheme.QuotedCell instanceof Function) { klass0 = Fargo.Scheme.QuotedCell; } else { klass0 = this.klass.SyntaxNode; } address0 = new klass0(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.QuotedCell instanceof Function)) { address0.extend(Fargo.Scheme.QuotedCell); } this._offset += text0.length; } else { address0 = null; } if (address0) { } else { this._offset = index1; var index3 = this._offset; var elements1 = []; var labelled1 = {}; var text1 = ""; var address4 = null; address4 = this.__consume__ignore(); if (address4) { elements1.push(address4); text1 += address4.textValue; labelled1.ignore = address4; var address5 = null; var index4 = this._offset; address5 = this.__consume__list(); if (address5) { } else { this._offset = index4; address5 = this.__consume__vector(); if (address5) { } else { this._offset = index4; address5 = this.__consume__atom(); if (address5) { } else { this._offset = index4; } } } if (address5) { elements1.push(address5); text1 += address5.textValue; var address6 = null; address6 = this.__consume__ignore(); if (address6) { elements1.push(address6); text1 += address6.textValue; labelled1.ignore = address6; } else { elements1 = null; this._offset = index3; } } else { elements1 = null; this._offset = index3; } } else { elements1 = null; this._offset = index3; } if (elements1) { this._offset = index3; var klass1 = null; if (Fargo.Scheme.Cell instanceof Function) { klass1 = Fargo.Scheme.Cell; } else { klass1 = this.klass.SyntaxNode; } address0 = new klass1(text1, this._offset, elements1, labelled1); if (!(Fargo.Scheme.Cell instanceof Function)) { address0.extend(Fargo.Scheme.Cell); } this._offset += text1.length; } else { address0 = null; } if (address0) { } else { this._offset = index1; } } return this._nodeCache.cell[index0] = address0; }, __consume__quote: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.quote = this._nodeCache.quote || {}; var cached = this._nodeCache.quote[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "'") { var klass0 = this.klass.SyntaxNode; address0 = new klass0("'", this._offset, []); this._offset += 1; } else { address0 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address0) { } else { this._offset = index1; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } if (slice2 === "`") { var klass1 = this.klass.SyntaxNode; address0 = new klass1("`", this._offset, []); this._offset += 1; } else { address0 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } if (address0) { } else { this._offset = index1; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 2); } else { slice4 = null; } if (slice4 === ",@") { var klass2 = this.klass.SyntaxNode; address0 = new klass2(",@", this._offset, []); this._offset += 2; } else { address0 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } if (address0) { } else { this._offset = index1; var slice6 = null; if (this._input.length > this._offset) { slice6 = this._input.substring(this._offset, this._offset + 1); } else { slice6 = null; } if (slice6 === ",") { var klass3 = this.klass.SyntaxNode; address0 = new klass3(",", this._offset, []); this._offset += 1; } else { address0 = null; var slice7 = null; if (this._input.length > this._offset) { slice7 = this._input.substring(this._offset, this._offset + 1); } else { slice7 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice7 || ""}; } } if (address0) { } else { this._offset = index1; } } } } return this._nodeCache.quote[index0] = address0; }, __consume__list: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.list = this._nodeCache.list || {}; var cached = this._nodeCache.list[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var index2 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "(") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("(", this._offset, []); this._offset += 1; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; address2 = this.__consume__cells(); if (address2) { elements0.push(address2); text0 += address2.textValue; labelled0.cells = address2; var address3 = null; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } if (slice2 === ")") { var klass1 = this.klass.SyntaxNode; address3 = new klass1(")", this._offset, []); this._offset += 1; } else { address3 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } if (address3) { elements0.push(address3); text0 += address3.textValue; } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } if (elements0) { this._offset = index2; var klass2 = this.klass.SyntaxNode; address0 = new klass2(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.List instanceof Function)) { address0.extend(Fargo.Scheme.List); } } else { this._offset = index1; var index3 = this._offset; var elements1 = []; var labelled1 = {}; var text1 = ""; var address4 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } if (slice4 === "[") { var klass3 = this.klass.SyntaxNode; address4 = new klass3("[", this._offset, []); this._offset += 1; } else { address4 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } if (address4) { elements1.push(address4); text1 += address4.textValue; var address5 = null; address5 = this.__consume__cells(); if (address5) { elements1.push(address5); text1 += address5.textValue; labelled1.cells = address5; var address6 = null; var slice6 = null; if (this._input.length > this._offset) { slice6 = this._input.substring(this._offset, this._offset + 1); } else { slice6 = null; } if (slice6 === "]") { var klass4 = this.klass.SyntaxNode; address6 = new klass4("]", this._offset, []); this._offset += 1; } else { address6 = null; var slice7 = null; if (this._input.length > this._offset) { slice7 = this._input.substring(this._offset, this._offset + 1); } else { slice7 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice7 || ""}; } } if (address6) { elements1.push(address6); text1 += address6.textValue; } else { elements1 = null; this._offset = index3; } } else { elements1 = null; this._offset = index3; } } else { elements1 = null; this._offset = index3; } if (elements1) { this._offset = index3; var klass5 = this.klass.SyntaxNode; address0 = new klass5(text1, this._offset, elements1, labelled1); this._offset += text1.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.List instanceof Function)) { address0.extend(Fargo.Scheme.List); } } else { this._offset = index1; } } return this._nodeCache.list[index0] = address0; }, __consume__cells: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.cells = this._nodeCache.cells || {}; var cached = this._nodeCache.cells[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var index2 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var remaining0 = 1; var index3 = this._offset; var elements1 = []; var text1 = ""; var address2 = true; while (address2) { address2 = this.__consume__cell(); if (address2) { elements1.push(address2); text1 += address2.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index3; var klass0 = this.klass.SyntaxNode; address1 = new klass0(text1, this._offset, elements1); this._offset += text1.length; } else { address1 = null; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address3 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === ".") { var klass1 = this.klass.SyntaxNode; address3 = new klass1(".", this._offset, []); this._offset += 1; } else { address3 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address3) { elements0.push(address3); text0 += address3.textValue; labelled0.dot = address3; var address4 = null; address4 = this.__consume__space(); if (address4) { elements0.push(address4); text0 += address4.textValue; labelled0.space = address4; var address5 = null; address5 = this.__consume__cell(); if (address5) { elements0.push(address5); text0 += address5.textValue; labelled0.cell = address5; } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } if (elements0) { this._offset = index2; var klass2 = this.klass.SyntaxNode; address0 = new klass2(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } if (address0) { } else { this._offset = index1; var remaining1 = 0; var index4 = this._offset; var elements2 = []; var text2 = ""; var address6 = true; while (address6) { address6 = this.__consume__cell(); if (address6) { elements2.push(address6); text2 += address6.textValue; remaining1 -= 1; } } if (remaining1 <= 0) { this._offset = index4; var klass3 = this.klass.SyntaxNode; address0 = new klass3(text2, this._offset, elements2); this._offset += text2.length; } else { address0 = null; } if (address0) { } else { this._offset = index1; } } return this._nodeCache.cells[index0] = address0; }, __consume__vector: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.vector = this._nodeCache.vector || {}; var cached = this._nodeCache.vector[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var index2 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 2); } else { slice0 = null; } if (slice0 === "#(") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("#(", this._offset, []); this._offset += 2; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var remaining0 = 0; var index3 = this._offset; var elements1 = []; var text1 = ""; var address3 = true; while (address3) { address3 = this.__consume__cell(); if (address3) { elements1.push(address3); text1 += address3.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index3; var klass1 = this.klass.SyntaxNode; address2 = new klass1(text1, this._offset, elements1); this._offset += text1.length; } else { address2 = null; } if (address2) { elements0.push(address2); text0 += address2.textValue; var address4 = null; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } if (slice2 === ")") { var klass2 = this.klass.SyntaxNode; address4 = new klass2(")", this._offset, []); this._offset += 1; } else { address4 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } if (address4) { elements0.push(address4); text0 += address4.textValue; } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } if (elements0) { this._offset = index2; var klass3 = this.klass.SyntaxNode; address0 = new klass3(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.Vector instanceof Function)) { address0.extend(Fargo.Scheme.Vector); } } else { this._offset = index1; var index4 = this._offset; var elements2 = []; var labelled1 = {}; var text2 = ""; var address5 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 2); } else { slice4 = null; } if (slice4 === "#[") { var klass4 = this.klass.SyntaxNode; address5 = new klass4("#[", this._offset, []); this._offset += 2; } else { address5 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } if (address5) { elements2.push(address5); text2 += address5.textValue; var address6 = null; var remaining1 = 0; var index5 = this._offset; var elements3 = []; var text3 = ""; var address7 = true; while (address7) { address7 = this.__consume__cell(); if (address7) { elements3.push(address7); text3 += address7.textValue; remaining1 -= 1; } } if (remaining1 <= 0) { this._offset = index5; var klass5 = this.klass.SyntaxNode; address6 = new klass5(text3, this._offset, elements3); this._offset += text3.length; } else { address6 = null; } if (address6) { elements2.push(address6); text2 += address6.textValue; var address8 = null; var slice6 = null; if (this._input.length > this._offset) { slice6 = this._input.substring(this._offset, this._offset + 1); } else { slice6 = null; } if (slice6 === "]") { var klass6 = this.klass.SyntaxNode; address8 = new klass6("]", this._offset, []); this._offset += 1; } else { address8 = null; var slice7 = null; if (this._input.length > this._offset) { slice7 = this._input.substring(this._offset, this._offset + 1); } else { slice7 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice7 || ""}; } } if (address8) { elements2.push(address8); text2 += address8.textValue; } else { elements2 = null; this._offset = index4; } } else { elements2 = null; this._offset = index4; } } else { elements2 = null; this._offset = index4; } if (elements2) { this._offset = index4; var klass7 = this.klass.SyntaxNode; address0 = new klass7(text2, this._offset, elements2, labelled1); this._offset += text2.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.Vector instanceof Function)) { address0.extend(Fargo.Scheme.Vector); } } else { this._offset = index1; } } return this._nodeCache.vector[index0] = address0; }, __consume__atom: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.atom = this._nodeCache.atom || {}; var cached = this._nodeCache.atom[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; address0 = this.__consume__datum(); if (address0) { } else { this._offset = index1; address0 = this.__consume__symbol(); if (address0) { } else { this._offset = index1; } } return this._nodeCache.atom[index0] = address0; }, __consume__datum: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.datum = this._nodeCache.datum || {}; var cached = this._nodeCache.datum[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var index2 = this._offset; address1 = this.__consume__boolean(); if (address1) { } else { this._offset = index2; address1 = this.__consume__number(); if (address1) { } else { this._offset = index2; address1 = this.__consume__character(); if (address1) { } else { this._offset = index2; address1 = this.__consume__string(); if (address1) { } else { this._offset = index2; } } } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var index3 = this._offset; var index4 = this._offset; var elements1 = []; var labelled1 = {}; var text1 = ""; var address3 = null; var index5 = this._offset; address3 = this.__consume__reserved(); this._offset = index5; if (!(address3)) { var klass0 = this.klass.SyntaxNode; address3 = new klass0("", this._offset, []); this._offset += 0; } else { address3 = null; } if (address3) { elements1.push(address3); text1 += address3.textValue; var address4 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } var temp0 = slice0; if (temp0 === null) { address4 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } else { var klass1 = this.klass.SyntaxNode; address4 = new klass1(temp0, this._offset, []); this._offset += 1; } if (address4) { elements1.push(address4); text1 += address4.textValue; } else { elements1 = null; this._offset = index4; } } else { elements1 = null; this._offset = index4; } if (elements1) { this._offset = index4; var klass2 = this.klass.SyntaxNode; address2 = new klass2(text1, this._offset, elements1, labelled1); this._offset += text1.length; } else { address2 = null; } this._offset = index3; if (!(address2)) { var klass3 = this.klass.SyntaxNode; address2 = new klass3("", this._offset, []); this._offset += 0; } else { address2 = null; } if (address2) { elements0.push(address2); text0 += address2.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass4 = null; if (Fargo.Scheme.Datum instanceof Function) { klass4 = Fargo.Scheme.Datum; } else { klass4 = this.klass.SyntaxNode; } address0 = new klass4(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.Datum instanceof Function)) { address0.extend(Fargo.Scheme.Datum); } this._offset += text0.length; } else { address0 = null; } return this._nodeCache.datum[index0] = address0; }, __consume__boolean: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.boolean = this._nodeCache.boolean || {}; var cached = this._nodeCache.boolean[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "#") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("#", this._offset, []); this._offset += 1; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } var temp0 = slice2; var match0 = null; if (match0 = temp0 && temp0.match(/^[tf]/)) { var klass1 = this.klass.SyntaxNode; address2 = new klass1(match0[0], this._offset, []); this._offset += 1; } else { address2 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[tf]", actual: slice3 || ""}; } } if (address2) { elements0.push(address2); text0 += address2.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass2 = null; if (Fargo.Scheme.Boolean instanceof Function) { klass2 = Fargo.Scheme.Boolean; } else { klass2 = this.klass.SyntaxNode; } address0 = new klass2(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.Boolean instanceof Function)) { address0.extend(Fargo.Scheme.Boolean); } this._offset += text0.length; } else { address0 = null; } return this._nodeCache.boolean[index0] = address0; }, __consume__number: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.number = this._nodeCache.number || {}; var cached = this._nodeCache.number[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var index2 = this._offset; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "-") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("-", this._offset, []); this._offset += 1; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { } else { this._offset = index2; var klass1 = this.klass.SyntaxNode; address1 = new klass1("", this._offset, []); this._offset += 0; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var index3 = this._offset; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } if (slice2 === "0") { var klass2 = this.klass.SyntaxNode; address2 = new klass2("0", this._offset, []); this._offset += 1; } else { address2 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } if (address2) { } else { this._offset = index3; var index4 = this._offset; var elements1 = []; var labelled1 = {}; var text1 = ""; var address3 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } var temp0 = slice4; var match0 = null; if (match0 = temp0 && temp0.match(/^[1-9]/)) { var klass3 = this.klass.SyntaxNode; address3 = new klass3(match0[0], this._offset, []); this._offset += 1; } else { address3 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[1-9]", actual: slice5 || ""}; } } if (address3) { elements1.push(address3); text1 += address3.textValue; var address4 = null; var remaining0 = 0; var index5 = this._offset; var elements2 = []; var text2 = ""; var address5 = true; while (address5) { var slice6 = null; if (this._input.length > this._offset) { slice6 = this._input.substring(this._offset, this._offset + 1); } else { slice6 = null; } var temp1 = slice6; var match1 = null; if (match1 = temp1 && temp1.match(/^[0-9]/)) { var klass4 = this.klass.SyntaxNode; address5 = new klass4(match1[0], this._offset, []); this._offset += 1; } else { address5 = null; var slice7 = null; if (this._input.length > this._offset) { slice7 = this._input.substring(this._offset, this._offset + 1); } else { slice7 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[0-9]", actual: slice7 || ""}; } } if (address5) { elements2.push(address5); text2 += address5.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index5; var klass5 = this.klass.SyntaxNode; address4 = new klass5(text2, this._offset, elements2); this._offset += text2.length; } else { address4 = null; } if (address4) { elements1.push(address4); text1 += address4.textValue; } else { elements1 = null; this._offset = index4; } } else { elements1 = null; this._offset = index4; } if (elements1) { this._offset = index4; var klass6 = this.klass.SyntaxNode; address2 = new klass6(text1, this._offset, elements1, labelled1); this._offset += text1.length; } else { address2 = null; } if (address2) { } else { this._offset = index3; } } if (address2) { elements0.push(address2); text0 += address2.textValue; var address6 = null; var index6 = this._offset; var index7 = this._offset; var elements3 = []; var labelled2 = {}; var text3 = ""; var address7 = null; var slice8 = null; if (this._input.length > this._offset) { slice8 = this._input.substring(this._offset, this._offset + 1); } else { slice8 = null; } if (slice8 === ".") { var klass7 = this.klass.SyntaxNode; address7 = new klass7(".", this._offset, []); this._offset += 1; } else { address7 = null; var slice9 = null; if (this._input.length > this._offset) { slice9 = this._input.substring(this._offset, this._offset + 1); } else { slice9 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice9 || ""}; } } if (address7) { elements3.push(address7); text3 += address7.textValue; var address8 = null; var remaining1 = 1; var index8 = this._offset; var elements4 = []; var text4 = ""; var address9 = true; while (address9) { var slice10 = null; if (this._input.length > this._offset) { slice10 = this._input.substring(this._offset, this._offset + 1); } else { slice10 = null; } var temp2 = slice10; var match2 = null; if (match2 = temp2 && temp2.match(/^[0-9]/)) { var klass8 = this.klass.SyntaxNode; address9 = new klass8(match2[0], this._offset, []); this._offset += 1; } else { address9 = null; var slice11 = null; if (this._input.length > this._offset) { slice11 = this._input.substring(this._offset, this._offset + 1); } else { slice11 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[0-9]", actual: slice11 || ""}; } } if (address9) { elements4.push(address9); text4 += address9.textValue; remaining1 -= 1; } } if (remaining1 <= 0) { this._offset = index8; var klass9 = this.klass.SyntaxNode; address8 = new klass9(text4, this._offset, elements4); this._offset += text4.length; } else { address8 = null; } if (address8) { elements3.push(address8); text3 += address8.textValue; } else { elements3 = null; this._offset = index7; } } else { elements3 = null; this._offset = index7; } if (elements3) { this._offset = index7; var klass10 = this.klass.SyntaxNode; address6 = new klass10(text3, this._offset, elements3, labelled2); this._offset += text3.length; } else { address6 = null; } if (address6) { } else { this._offset = index6; var klass11 = this.klass.SyntaxNode; address6 = new klass11("", this._offset, []); this._offset += 0; } if (address6) { elements0.push(address6); text0 += address6.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass12 = null; if (Fargo.Scheme.Number instanceof Function) { klass12 = Fargo.Scheme.Number; } else { klass12 = this.klass.SyntaxNode; } address0 = new klass12(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.Number instanceof Function)) { address0.extend(Fargo.Scheme.Number); } this._offset += text0.length; } else { address0 = null; } return this._nodeCache.number[index0] = address0; }, __consume__character: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.character = this._nodeCache.character || {}; var cached = this._nodeCache.character[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 2); } else { slice0 = null; } if (slice0 === "#\\") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("#\\", this._offset, []); this._offset += 2; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var index2 = this._offset; address2 = this.__consume__symbol(); if (address2) { } else { this._offset = index2; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } var temp0 = slice2; if (temp0 === null) { address2 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } else { var klass1 = this.klass.SyntaxNode; address2 = new klass1(temp0, this._offset, []); this._offset += 1; } if (address2) { } else { this._offset = index2; } } if (address2) { elements0.push(address2); text0 += address2.textValue; labelled0.glyph = address2; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass2 = this.klass.SyntaxNode; address0 = new klass2(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } return this._nodeCache.character[index0] = address0; }, __consume__string: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.string = this._nodeCache.string || {}; var cached = this._nodeCache.string[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "\"") { var klass0 = this.klass.SyntaxNode; address1 = new klass0("\"", this._offset, []); this._offset += 1; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var remaining0 = 0; var index2 = this._offset; var elements1 = []; var text1 = ""; var address3 = true; while (address3) { var index3 = this._offset; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 2); } else { slice2 = null; } if (slice2 === "\\\"") { var klass1 = this.klass.SyntaxNode; address3 = new klass1("\\\"", this._offset, []); this._offset += 2; } else { address3 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } if (address3) { } else { this._offset = index3; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } var temp0 = slice4; var match0 = null; if (match0 = temp0 && temp0.match(/^[^"]/)) { var klass2 = this.klass.SyntaxNode; address3 = new klass2(match0[0], this._offset, []); this._offset += 1; } else { address3 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[^\"]", actual: slice5 || ""}; } } if (address3) { } else { this._offset = index3; } } if (address3) { elements1.push(address3); text1 += address3.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index2; var klass3 = this.klass.SyntaxNode; address2 = new klass3(text1, this._offset, elements1); this._offset += text1.length; } else { address2 = null; } if (address2) { elements0.push(address2); text0 += address2.textValue; var address4 = null; var slice6 = null; if (this._input.length > this._offset) { slice6 = this._input.substring(this._offset, this._offset + 1); } else { slice6 = null; } if (slice6 === "\"") { var klass4 = this.klass.SyntaxNode; address4 = new klass4("\"", this._offset, []); this._offset += 1; } else { address4 = null; var slice7 = null; if (this._input.length > this._offset) { slice7 = this._input.substring(this._offset, this._offset + 1); } else { slice7 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice7 || ""}; } } if (address4) { elements0.push(address4); text0 += address4.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass5 = null; if (Fargo.Scheme.String instanceof Function) { klass5 = Fargo.Scheme.String; } else { klass5 = this.klass.SyntaxNode; } address0 = new klass5(text0, this._offset, elements0, labelled0); if (!(Fargo.Scheme.String instanceof Function)) { address0.extend(Fargo.Scheme.String); } this._offset += text0.length; } else { address0 = null; } return this._nodeCache.string[index0] = address0; }, __consume__symbol: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.symbol = this._nodeCache.symbol || {}; var cached = this._nodeCache.symbol[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var index2 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var index3 = this._offset; var elements1 = []; var labelled1 = {}; var text1 = ""; var address2 = null; var index4 = this._offset; address2 = this.__consume__delimiter(); this._offset = index4; if (!(address2)) { var klass0 = this.klass.SyntaxNode; address2 = new klass0("", this._offset, []); this._offset += 0; } else { address2 = null; } if (address2) { elements1.push(address2); text1 += address2.textValue; var address3 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } var temp0 = slice0; if (temp0 === null) { address3 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } else { var klass1 = this.klass.SyntaxNode; address3 = new klass1(temp0, this._offset, []); this._offset += 1; } if (address3) { elements1.push(address3); text1 += address3.textValue; } else { elements1 = null; this._offset = index3; } } else { elements1 = null; this._offset = index3; } if (elements1) { this._offset = index3; var klass2 = this.klass.SyntaxNode; address1 = new klass2(text1, this._offset, elements1, labelled1); this._offset += text1.length; } else { address1 = null; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address4 = null; var remaining0 = 1; var index5 = this._offset; var elements2 = []; var text2 = ""; var address5 = true; while (address5) { var index6 = this._offset; var elements3 = []; var labelled2 = {}; var text3 = ""; var address6 = null; var index7 = this._offset; address6 = this.__consume__delimiter(); this._offset = index7; if (!(address6)) { var klass3 = this.klass.SyntaxNode; address6 = new klass3("", this._offset, []); this._offset += 0; } else { address6 = null; } if (address6) { elements3.push(address6); text3 += address6.textValue; var address7 = null; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } var temp1 = slice2; if (temp1 === null) { address7 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice3 || ""}; } } else { var klass4 = this.klass.SyntaxNode; address7 = new klass4(temp1, this._offset, []); this._offset += 1; } if (address7) { elements3.push(address7); text3 += address7.textValue; } else { elements3 = null; this._offset = index6; } } else { elements3 = null; this._offset = index6; } if (elements3) { this._offset = index6; var klass5 = this.klass.SyntaxNode; address5 = new klass5(text3, this._offset, elements3, labelled2); this._offset += text3.length; } else { address5 = null; } if (address5) { elements2.push(address5); text2 += address5.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index5; var klass6 = this.klass.SyntaxNode; address4 = new klass6(text2, this._offset, elements2); this._offset += text2.length; } else { address4 = null; } if (address4) { elements0.push(address4); text0 += address4.textValue; } else { elements0 = null; this._offset = index2; } } else { elements0 = null; this._offset = index2; } if (elements0) { this._offset = index2; var klass7 = this.klass.SyntaxNode; address0 = new klass7(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.Symbol instanceof Function)) { address0.extend(Fargo.Scheme.Symbol); } } else { this._offset = index1; var index8 = this._offset; var elements4 = []; var labelled3 = {}; var text4 = ""; var address8 = null; var index9 = this._offset; address8 = this.__consume__reserved(); this._offset = index9; if (!(address8)) { var klass8 = this.klass.SyntaxNode; address8 = new klass8("", this._offset, []); this._offset += 0; } else { address8 = null; } if (address8) { elements4.push(address8); text4 += address8.textValue; var address9 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } var temp2 = slice4; if (temp2 === null) { address9 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } else { var klass9 = this.klass.SyntaxNode; address9 = new klass9(temp2, this._offset, []); this._offset += 1; } if (address9) { elements4.push(address9); text4 += address9.textValue; } else { elements4 = null; this._offset = index8; } } else { elements4 = null; this._offset = index8; } if (elements4) { this._offset = index8; var klass10 = this.klass.SyntaxNode; address0 = new klass10(text4, this._offset, elements4, labelled3); this._offset += text4.length; } else { address0 = null; } if (address0) { if (!(Fargo.Scheme.Symbol instanceof Function)) { address0.extend(Fargo.Scheme.Symbol); } } else { this._offset = index1; } } return this._nodeCache.symbol[index0] = address0; }, __consume__reserved: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.reserved = this._nodeCache.reserved || {}; var cached = this._nodeCache.reserved[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === ".") { var klass0 = this.klass.SyntaxNode; address0 = new klass0(".", this._offset, []); this._offset += 1; } else { address0 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address0) { } else { this._offset = index1; address0 = this.__consume__delimiter(); if (address0) { } else { this._offset = index1; } } return this._nodeCache.reserved[index0] = address0; }, __consume__delimiter: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.delimiter = this._nodeCache.delimiter || {}; var cached = this._nodeCache.delimiter[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; address0 = this.__consume__quote(); if (address0) { } else { this._offset = index1; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === "#") { var klass0 = this.klass.SyntaxNode; address0 = new klass0("#", this._offset, []); this._offset += 1; } else { address0 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address0) { } else { this._offset = index1; address0 = this.__consume__paren(); if (address0) { } else { this._offset = index1; address0 = this.__consume__space(); if (address0) { } else { this._offset = index1; } } } } return this._nodeCache.delimiter[index0] = address0; }, __consume__paren: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.paren = this._nodeCache.paren || {}; var cached = this._nodeCache.paren[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } var temp0 = slice0; var match0 = null; if (match0 = temp0 && temp0.match(/^[\(\)\[\]]/)) { var klass0 = this.klass.SyntaxNode; address0 = new klass0(match0[0], this._offset, []); this._offset += 1; } else { address0 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[\(\)\[\]]", actual: slice1 || ""}; } } return this._nodeCache.paren[index0] = address0; }, __consume__space: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.space = this._nodeCache.space || {}; var cached = this._nodeCache.space[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } var temp0 = slice0; var match0 = null; if (match0 = temp0 && temp0.match(/^[\s\n\r\t]/)) { var klass0 = this.klass.SyntaxNode; address0 = new klass0(match0[0], this._offset, []); this._offset += 1; } else { address0 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[\s\n\r\t]", actual: slice1 || ""}; } } return this._nodeCache.space[index0] = address0; }, __consume__ignore: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.ignore = this._nodeCache.ignore || {}; var cached = this._nodeCache.ignore[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var remaining0 = 0; var index2 = this._offset; var elements1 = []; var text1 = ""; var address2 = true; while (address2) { address2 = this.__consume__space(); if (address2) { elements1.push(address2); text1 += address2.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index2; var klass0 = this.klass.SyntaxNode; address1 = new klass0(text1, this._offset, elements1); this._offset += text1.length; } else { address1 = null; } if (address1) { elements0.push(address1); text0 += address1.textValue; var address3 = null; var index3 = this._offset; var index4 = this._offset; var elements2 = []; var labelled1 = {}; var text2 = ""; var address4 = null; address4 = this.__consume__comment(); if (address4) { elements2.push(address4); text2 += address4.textValue; labelled1.comment = address4; var address5 = null; address5 = this.__consume__ignore(); if (address5) { elements2.push(address5); text2 += address5.textValue; labelled1.ignore = address5; } else { elements2 = null; this._offset = index4; } } else { elements2 = null; this._offset = index4; } if (elements2) { this._offset = index4; var klass1 = this.klass.SyntaxNode; address3 = new klass1(text2, this._offset, elements2, labelled1); this._offset += text2.length; } else { address3 = null; } if (address3) { } else { this._offset = index3; var klass2 = this.klass.SyntaxNode; address3 = new klass2("", this._offset, []); this._offset += 0; } if (address3) { elements0.push(address3); text0 += address3.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass3 = this.klass.SyntaxNode; address0 = new klass3(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } return this._nodeCache.ignore[index0] = address0; }, __consume__comment: function(input) { var address0 = null; var index0 = this._offset; this._nodeCache.comment = this._nodeCache.comment || {}; var cached = this._nodeCache.comment[index0]; if (cached) { this._offset += cached.textValue.length; return cached; } var index1 = this._offset; var elements0 = []; var labelled0 = {}; var text0 = ""; var address1 = null; var slice0 = null; if (this._input.length > this._offset) { slice0 = this._input.substring(this._offset, this._offset + 1); } else { slice0 = null; } if (slice0 === ";") { var klass0 = this.klass.SyntaxNode; address1 = new klass0(";", this._offset, []); this._offset += 1; } else { address1 = null; var slice1 = null; if (this._input.length > this._offset) { slice1 = this._input.substring(this._offset, this._offset + 1); } else { slice1 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice1 || ""}; } } if (address1) { elements0.push(address1); text0 += address1.textValue; var address2 = null; var remaining0 = 0; var index2 = this._offset; var elements1 = []; var text1 = ""; var address3 = true; while (address3) { var index3 = this._offset; var elements2 = []; var labelled1 = {}; var text2 = ""; var address4 = null; var index4 = this._offset; var slice2 = null; if (this._input.length > this._offset) { slice2 = this._input.substring(this._offset, this._offset + 1); } else { slice2 = null; } var temp0 = slice2; var match0 = null; if (match0 = temp0 && temp0.match(/^[\n\r]/)) { var klass1 = this.klass.SyntaxNode; address4 = new klass1(match0[0], this._offset, []); this._offset += 1; } else { address4 = null; var slice3 = null; if (this._input.length > this._offset) { slice3 = this._input.substring(this._offset, this._offset + 1); } else { slice3 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "[\n\r]", actual: slice3 || ""}; } } this._offset = index4; if (!(address4)) { var klass2 = this.klass.SyntaxNode; address4 = new klass2("", this._offset, []); this._offset += 0; } else { address4 = null; } if (address4) { elements2.push(address4); text2 += address4.textValue; var address5 = null; var slice4 = null; if (this._input.length > this._offset) { slice4 = this._input.substring(this._offset, this._offset + 1); } else { slice4 = null; } var temp1 = slice4; if (temp1 === null) { address5 = null; var slice5 = null; if (this._input.length > this._offset) { slice5 = this._input.substring(this._offset, this._offset + 1); } else { slice5 = null; } if (!this.error || this.error.offset <= this._offset) { this.error = this.klass.lastError = {input: this._input, offset: this._offset, expected: "", actual: slice5 || ""}; } } else { var klass3 = this.klass.SyntaxNode; address5 = new klass3(temp1, this._offset, []); this._offset += 1; } if (address5) { elements2.push(address5); text2 += address5.textValue; } else { elements2 = null; this._offset = index3; } } else { elements2 = null; this._offset = index3; } if (elements2) { this._offset = index3; var klass4 = this.klass.SyntaxNode; address3 = new klass4(text2, this._offset, elements2, labelled1); this._offset += text2.length; } else { address3 = null; } if (address3) { elements1.push(address3); text1 += address3.textValue; remaining0 -= 1; } } if (remaining0 <= 0) { this._offset = index2; var klass5 = this.klass.SyntaxNode; address2 = new klass5(text1, this._offset, elements1); this._offset += text1.length; } else { address2 = null; } if (address2) { elements0.push(address2); text0 += address2.textValue; } else { elements0 = null; this._offset = index1; } } else { elements0 = null; this._offset = index1; } if (elements0) { this._offset = index1; var klass6 = this.klass.SyntaxNode; address0 = new klass6(text0, this._offset, elements0, labelled0); this._offset += text0.length; } else { address0 = null; } return this._nodeCache.comment[index0] = address0; } }); Fargo.SchemeParser = new JS.Class("Fargo.SchemeParser", { include: Fargo.Scheme, initialize: function(input) { this._input = input; this._offset = 0; this._nodeCache = {}; }, parse: function() { var result = this["__consume__" + this.root](); return this._offset === this._input.length ? result : null; }, extend: { parse: function(input) { var parser = new this(input); return parser.parse(); } } }); Fargo.SchemeParser.SyntaxNode = new JS.Class("Fargo.SchemeParser.SyntaxNode", { include: JS.Enumerable, initialize: function(textValue, offset, elements, properties) { this.textValue = textValue; this.offset = offset; this.elements = elements || []; if (!properties) return; for (var key in properties) this[key] = properties[key]; }, forEach: function(block, context) { for (var i = 0, n = this.elements.length; i < n; i++) block.call(context, this.elements[i], i); } }); Fargo.SchemeParser.formatError = function (error) { var lines = error.input.split(/\n/g), lineNo = 0, offset = 0; while (offset < error.offset) { offset += lines[lineNo].length + 1; lineNo += 1; } var message = 'Line ' + lineNo + ': expected ' + error.expected + '\n', line = lines[lineNo - 1]; message += line + '\n'; offset -= line.length + 1; while (offset < error.offset) { message += ' '; offset += 1; } return message + '^'; }; ================================================ FILE: source/fargo/scheme.peg ================================================ grammar Fargo.Scheme program <- shebang? cell* shebang <- space* "#!" (![\n\r] .)* cell <- ignore quote cell / ignore (list / vector / atom) ignore quote <- "'" / "`" / ",@" / "," list <- ("(" cells ")" / "[" cells "]") cells <- cell+ dot:"." space cell / cell* vector <- ("#(" cell* ")" / "#[" cell* "]") atom <- datum / symbol datum <- (boolean / number / character / string) !(!reserved .) boolean <- "#" [tf] number <- "-"? ("0" / [1-9] [0-9]*) ("." [0-9]+)? character <- "#\\" glyph:(symbol / .) string <- "\"" ("\\\"" / [^"])* "\"" symbol <- ((!delimiter .) (!delimiter .)+ / (!reserved .)) reserved <- "." / delimiter delimiter <- quote / "#" / paren / space paren <- [\(\)\[\]] space <- [\s\n\r\t] ignore <- space* (comment ignore)? comment <- ";" (![\n\r] .)* ================================================ FILE: source/fargo/scheme_nodes.js ================================================ Fargo.Scheme.Program = new JS.Module({ eval: function(scope) { var expr = this.convert(), value = null, nil = Fargo.Runtime.Cons.NULL; while (expr !== nil) { value = Fargo.evaluate(expr.car, scope); expr = expr.cdr; } return value; }, convert: function() { if (this._ast) return this._ast; var cells = this.elements[1].elements, cons = Fargo.Runtime.Cons, list = cons.NULL, i = cells.length; while (i--) list = new cons(cells[i].convert(), list); return this._ast = list; } }); Fargo.Scheme.QuotedCell = new JS.Module({ SHORTHANDS: { "'": 'quote', "`": 'quasiquote', ",": 'unquote', ",@": 'unquote-splicing' }, convert: function() { var runtime = Fargo.Runtime, macro = this.SHORTHANDS[this.elements[1].textValue]; return new runtime.Cons(new runtime.Symbol(macro), new runtime.Cons(this.cell.convert(), runtime.Cons.NULL)); } }); Fargo.Scheme.Cell = new JS.Module({ convert: function() { return this.elements[1].convert(); } }); Fargo.Scheme.Datum = new JS.Module({ convert: function() { return this.elements[0].convert(); } }); Fargo.Scheme.List = new JS.Module({ convert: function() { if (this._ast) return this._ast; var cells = this.cells.dot ? this.cells.elements[0].elements : this.cells.elements, elems = [], i = cells.length; while (i--) elems[i] = cells[i].convert(); var tail = this.cells.dot && this.cells.elements[3].convert(); this._ast = Fargo.Runtime.Cons.list(elems, tail); return this._ast; } }); Fargo.Scheme.Vector = new JS.Module({ convert: function() { if (this._ast) return this._ast; var cells = this.elements[1].elements, elems = [], i = cells.length; while (i--) elems[i] = cells[i].convert(); return this._ast = new Fargo.Runtime.Vector(elems); } }); Fargo.Scheme.Boolean = new JS.Module({ convert: function() { return this.textValue === '#t'; } }); Fargo.Scheme.Number = new JS.Module({ convert: function() { return parseFloat(this.textValue, 10); } }); Fargo.Scheme.String = new JS.Module({ convert: function() { return eval(this.textValue); } }); Fargo.Scheme.Symbol = new JS.Module({ convert: function() { return new Fargo.Runtime.Symbol(this.textValue); } }); ================================================ FILE: source/fargo.js ================================================ Fargo = new JS.Module('Fargo'); Fargo.extend({ VERSION: '0.0.1-preview', Runtime: new JS.Class({ initialize: function() { this.stack = new this.klass.Stackless(); this.scope = new this.klass.TopLevel(this); }, define: function(name, value) { return this.scope.define(name, value); }, syntax: function(name, value) { return this.scope.syntax(name, value); }, run: function(path) { return this.scope.run(path); } }), clone: function(value) { if (value && value.clone) return value.clone(); return value; }, evaluate: function(expression, scope) { if (expression && expression.klass === Fargo.Runtime.Value) return expression.value; if (!expression || !expression.eval) return expression; return expression.eval(scope); }, freeze: function(value) { if (value && value.freeze) value.freeze(); return value; }, stringify: function(object) { if (typeof object === 'boolean') return object ? '#t' : '#f'; if (typeof object === 'string') return JSON.stringify(object); if (typeof object === 'number') return object.toString(10); return object.toString(); }, dirname: function(path) { return path.replace(/\/[^\/]*$/g, ''); }, path: function() { return Array.prototype.join.call(arguments, '/') .replace(/\/+/g, '/'); }, puts: function(string) { if (typeof require === 'function') require('sys').puts(string); }, loadJavaScript: function(path) { if (typeof require === 'function') return require(path); var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.type = 'text/javascript'; script.text = this.readFile(path); head.appendChild(script); }, readFile: function(path) { if (typeof require === 'function') return require('fs').readFileSync(path).toString(); var data = null, xhr = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); xhr.open('GET', path, false); xhr.onreadystatechange = function() { if (xhr.readyState !== 4) return; data = xhr.responseText; xhr.onreadystatechange = function() {}; xhr = null; }; xhr.send(null); return data; } }); ================================================ FILE: test.js ================================================ var path = require('path'), assert = require('assert'), sys = require('sys'); JSCLASS_PATH = './build/js.class'; FARGO_PATH = path.dirname(__filename) + '/build'; TEST_PATH = path.dirname(__filename) + '/vendor/heist/test/scheme_tests'; require(JSCLASS_PATH + '/loader'); JS.require('JS.Test'); require(FARGO_PATH + '/fargo') var runtime = new Fargo.Runtime(), test = new JS.Singleton(JS.Test.Unit.Assertions); runtime.define('assert', function(truthy) { test.assert(truthy); return true; }); runtime.define('assert-equal', function(expected, actual) { test.assertEqual(expected, actual); return true; }); runtime.syntax('assert-raise', function(scope, cells) { sys.debug('Not implemented: assert-raise ' + cells); return true; }); // runtime.run(TEST_PATH + '/arithmetic.scm'); runtime.run(TEST_PATH + '/booleans.scm'); runtime.run(TEST_PATH + '/closures.scm'); runtime.run(TEST_PATH + '/conditionals.scm'); runtime.run(TEST_PATH + '/define_functions.scm'); // runtime.run(TEST_PATH + '/define_values.scm'); runtime.run(TEST_PATH + '/delay.scm'); // runtime.run(TEST_PATH + '/equivalence.scm'); runtime.run(TEST_PATH + '/functional.scm'); runtime.run(TEST_PATH + '/let.scm'); runtime.run(TEST_PATH + '/lists.scm'); runtime.run(TEST_PATH + '/macros.scm'); runtime.run(TEST_PATH + '/unhygienic.scm'); // runtime.run(TEST_PATH + '/hygienic.scm'); // runtime.run(TEST_PATH + '/numbers.scm'); // runtime.run(TEST_PATH + '/protection.scm'); // runtime.run(TEST_PATH + '/strings.scm'); runtime.run(TEST_PATH + '/vectors.scm'); ================================================ FILE: try-fargo/analytics.js ================================================ var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-873493-9']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); ================================================ FILE: try-fargo/index.html ================================================ Try Fargo
================================================ FILE: try-fargo/javascripts/packages.js ================================================ JS.Packages(function() { with(this) { file('/javascripts/fargo/fargo-min.js') .provides('Fargo') .requires('JS.Class', 'JS.Module', 'JS.Enumerable'); file('/javascripts/jquery-console/jquery-1.4.2.min.js') .provides('jQuery'); file('/javascripts/jquery-console/jquery.console.js') .provides('jQuery.fn.console') .requires('jQuery'); }}); ================================================ FILE: try-fargo/style.css ================================================ html { background: #ddf2fd; background-image: -webkit-gradient(radial, 50% 40%, 5, 40% 40%, 800, from(#ddf2fd), to(#75bce1)); } body { color: #444; margin: 0; padding: 0; font: 13px/1.5 FreeSans, Helvetica, Arial, sans-serif; } #container { margin: 60px auto; width: 960px; height: 480px; -moz-box-shadow: 0 10px 50px #888; -webkit-box-shadow: 0 10px 50px #888; box-shadow: 0 10px 50px #888; } #sidebar { background: #fff; float: left; padding: 8px 20px; width: 320px; height: 464px; } h1 { color: #6f3d1b; font-size: 300%; margin: 0 -20px; padding: 0 20px; border-bottom: 1px solid #ccc; text-transform: uppercase; } p { margin: 1.5em 0; } a { color: #50b0d7; font-weight: bold; text-decoration: none; } tt { background: #f0f0f0; } .jquery-console-inner { background: #333; color: #b3dc47; float: left; padding: 20px; width: 560px; height: 440px; overflow: auto; font-size: 120%; font-family: Monaco, Courier New, monospace; } .jquery-console-cursor { background: #b3dc47; }