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 !== '<EOF>') {
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 '#<procedure' + name + '>';
},
_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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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: "<any char>", actual: slice5 || "<EOF>"};
}
} 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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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: "<any char>", actual: slice1 || "<EOF>"};
}
} 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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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: "<any char>", actual: slice3 || "<EOF>"};
}
} 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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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: "<any char>", actual: slice1 || "<EOF>"};
}
} 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: "<any char>", actual: slice3 || "<EOF>"};
}
} 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: "<any char>", actual: slice5 || "<EOF>"};
}
} 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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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 || "<EOF>"};
}
}
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: "<any char>", actual: slice5 || "<EOF>"};
}
} 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* <Fargo.Scheme.Program>
shebang <- space* "#!" (![\n\r] .)*
cell <- ignore quote cell <Fargo.Scheme.QuotedCell>
/ ignore (list / vector / atom) ignore <Fargo.Scheme.Cell>
quote <- "'" / "`" / ",@" / ","
list <- ("(" cells ")" / "[" cells "]") <Fargo.Scheme.List>
cells <- cell+ dot:"." space cell / cell*
vector <- ("#(" cell* ")" / "#[" cell* "]") <Fargo.Scheme.Vector>
atom <- datum / symbol
datum <- (boolean / number / character / string) !(!reserved .) <Fargo.Scheme.Datum>
boolean <- "#" [tf] <Fargo.Scheme.Boolean>
number <- "-"? ("0" / [1-9] [0-9]*) ("." [0-9]+)? <Fargo.Scheme.Number>
character <- "#\\" glyph:(symbol / .)
string <- "\"" ("\\\"" / [^"])* "\"" <Fargo.Scheme.String>
symbol <- ((!delimiter .) (!delimiter .)+ / (!reserved .)) <Fargo.Scheme.Symbol>
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
================================================
<!doctype html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Try Fargo</title>
<link rel="stylesheet" href="/style.css">
<script type="text/javascript" src="/javascripts/fargo/js.class/loader.js"></script>
<script type="text/javascript" src="/javascripts/packages.js"></script>
</head>
<body>
<!--
Hello-world fiber example using set-timeout and alert
(define (get-message)
(define f (current-fiber))
(set-timeout (lambda ()
(f "Hello, world!")
) 5000)
(yield))
(define main (fiber ()
; Look ma, it looks synchronous!
(define msg (get-message))
(alert msg)
))
-->
<div id="container">
<div id="sidebar">
<h1>Fargo //</h1>
<p>An experimental language to improve how we work with asynchronous
systems in JavaScript. It runs on <a href="http://nodejs.org">Node.js</a>
and in browsers.</p>
<p>Its core is a modified R5RS Scheme. It has tail-recursion and
<tt>syntax-rules</tt> macros, and uses the core library from
<a href="http://github.com/jcoglan/heist">Heist</a>. Data types are
booleans <tt>#t</tt>/<tt>#f</tt>, numbers, symbols, strings, lists
<tt>(a b c)</tt> and vectors <tt>#(a b c)</tt>. Quasiquoting with
<tt>'</tt>/<tt>`</tt>/<tt>,</tt>/<tt>,@</tt> is supported.</p>
<p>Instead of <tt>call/cc</tt>, Fargo supports Ruby-style fibers for
pausing and resuming async work. View source for an example using
<tt>set-timeout</tt>. You can find out more over on
<a href="http://github.com/jcoglan/fargo">GitHub</a>.</p>
<p><tt>(download "0.0.1-preview")</tt></p>
<p>MIT licensed, © 2011 <a href="http://jcoglan.com">James Coglan</a>.</p>
</div>
<div id="fargo-console"></div>
</div>
<script type="text/javascript">
window.FARGO_PATH = '/javascripts/fargo';
JS.require('jQuery.fn.console', 'Fargo', function() {
var runtime = new Fargo.Runtime();
runtime.define('alert', function(message) {
alert(message);
return message;
});
runtime.define('download', function(version) {
window.location = '/downloads/fargo-' + version + '.zip';
return true;
});
var OPTIONS = {
commandValidate: function(line) {
return line.replace(/\s/, '') !== '';
},
commandHandle: function(line) {
var parser = new Fargo.SchemeParser(line),
program = parser.parse(),
result;
if (!program) {
if (parser.error.actual === '<EOF>')
return fargoConsole.continuedPrompt = true;
fargoConsole.continuedPrompt = false;
return Fargo.SchemeParser.formatError(parser.error);
}
try {
result = program.eval(runtime.scope);
return result === undefined ? '' : '; => ' + Fargo.stringify(result);
} catch (e) {
return e.toString();
} finally {
fargoConsole.continuedPrompt = false;
}
},
welcomeMessage: 'Fargo ' + Fargo.VERSION + '\ne.g. (alert "Hello, world!")',
animateScroll: true,
autofocus: true,
promptHistory: true,
promptLabel: '> ',
continuedPrompt: true,
continuedPromptLabel: ' '
};
window.fargoConsole = jQuery('#fargo-console').console(OPTIONS);
});
</script>
</body>
</html>
================================================
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;
}
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
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (173K chars).
[
{
"path": ".gitignore",
"chars": 67,
"preview": "Gemfile.lock\nbuild\ntry-fargo/javascripts/fargo\ntry-fargo/downloads\n"
},
{
"path": ".gitmodules",
"chars": 338,
"preview": "[submodule \"vendor/js.class\"]\n\tpath = vendor/js.class\n\turl = git://github.com/jcoglan/js.class.git\n[submodule \"vendor/he"
},
{
"path": "Gemfile",
"chars": 29,
"preview": "source :rubygems\ngem 'jake'\n\n"
},
{
"path": "Jakefile",
"chars": 697,
"preview": "require 'fileutils'\n\njake_hook :build_complete do |build|\n FileUtils.copy_entry build.source_dir + '/fargo/lib',\n "
},
{
"path": "README.markdown",
"chars": 6549,
"preview": "# Fargo\n\nTry it out at http://fargo.jcoglan.com\n\nFargo is a programming language that runs on Node.js. It's designed to "
},
{
"path": "bin/fargo",
"chars": 1571,
"preview": "#!/usr/bin/env node\n\nvar path = require('path'),\n sys = require('sys'),\n rl = require('readline');\n\nJSCLASS_PAT"
},
{
"path": "examples/demo.scm",
"chars": 595,
"preview": "(define factorial (lambda (x)\n (if (= 0 x)\n 1\n (* (factorial (- x 1))\n x))))\n\n(puts (factorial 2000))"
},
{
"path": "examples/fibers.scm",
"chars": 275,
"preview": "(define stream (fiber (max)\n (do ((i 0 (+ 1 i)))\n ((eqv? max i) 'done)\n (yield i))))\n\n(puts (stream 2))\n(puts ("
},
{
"path": "examples/http.scm",
"chars": 209,
"preview": "(load \"./lib-http.js\")\n\n(define (fiber-http-get url)\n (http-get url (current-fiber))\n (yield))\n\n(define program (fiber"
},
{
"path": "examples/lib-http.js",
"chars": 466,
"preview": "Fargo.runtime.define('http-get', function(url, callback) {\n var uri = require('url').parse(url),\n client = require"
},
{
"path": "jake.yml",
"chars": 819,
"preview": "---\nsource_directory: source\nbuild_directory: build\nlayout: together\n\nbuilds:\n src:\n suffix: "
},
{
"path": "source/fargo/lib/primitives.js",
"chars": 8861,
"preview": "var Runtime = Fargo.Runtime,\n Cons = Runtime.Cons,\n Symbol = Runtime.Symbol,\n NULL = Cons.NULL;\n\n//====="
},
{
"path": "source/fargo/lib/timers.js",
"chars": 451,
"preview": "Fargo.runtime.define('set-timeout', function(procedure, millis) {\n return setTimeout(function() { procedure.exec() }, m"
},
{
"path": "source/fargo/runtime/callable/fiber.js",
"chars": 737,
"preview": "Fargo.Runtime.extend({\n Fiber: new JS.Class(Fargo.Runtime.Procedure, {\n apply: function(args) {\n var R = Fargo."
},
{
"path": "source/fargo/runtime/callable/macro/expansion.js",
"chars": 3242,
"preview": "Fargo.Runtime.Macro.extend({\n Expansion: new JS.Class({\n initialize: function(lexicalScope, callingScope, template, "
},
{
"path": "source/fargo/runtime/callable/macro/matches.js",
"chars": 1611,
"preview": "Fargo.Runtime.Macro.extend({\n Matches: new JS.Class({\n initialize: function(pattern, formals) {\n this._data = {"
},
{
"path": "source/fargo/runtime/callable/macro/tree.js",
"chars": 1417,
"preview": "Fargo.Runtime.Macro.extend({\n Tree: new JS.Class({\n initialize: function(name) {\n this._name = name;\n thi"
},
{
"path": "source/fargo/runtime/callable/macro.js",
"chars": 5415,
"preview": "Fargo.Runtime.extend({\n Macro: new JS.Class(Fargo.Runtime.Procedure, {\n extend: {\n ELLIPSIS: new Fargo.Runtime."
},
{
"path": "source/fargo/runtime/callable/procedure.js",
"chars": 1694,
"preview": "Fargo.Runtime.extend({\n Procedure: new JS.Class({\n initialize: function(scope, params, body) {\n this._lexicalSc"
},
{
"path": "source/fargo/runtime/callable/syntax.js",
"chars": 173,
"preview": "Fargo.Runtime.extend({\n Syntax: new JS.Class(Fargo.Runtime.Procedure, {\n call: function(scope, cells) {\n return"
},
{
"path": "source/fargo/runtime/data/cons.js",
"chars": 2271,
"preview": "Fargo.Runtime.extend({\n Cons: new JS.Class({\n include: JS.Enumerable,\n \n initialize: function(car, cdr) {\n "
},
{
"path": "source/fargo/runtime/data/symbol.js",
"chars": 382,
"preview": "Fargo.Runtime.extend({\n Symbol: new JS.Class({\n initialize: function(name) {\n this.name = name;\n },\n \n "
},
{
"path": "source/fargo/runtime/data/vector.js",
"chars": 1322,
"preview": "Fargo.Runtime.extend({\n Vector: new JS.Class({\n include: JS.Enumerable,\n \n initialize: function(elements) {\n "
},
{
"path": "source/fargo/runtime/frame.js",
"chars": 3063,
"preview": "Fargo.Runtime.extend({\n Frame: new JS.Class({\n initialize: function(expression, scope) {\n this._reset(expressio"
},
{
"path": "source/fargo/runtime/scope.js",
"chars": 2379,
"preview": "Fargo.Runtime.extend({\n Scope: new JS.Class({\n initialize: function(runtime, parent) {\n this.runtime = runtime;"
},
{
"path": "source/fargo/runtime/stack.js",
"chars": 1759,
"preview": "Fargo.Runtime.extend({\n Stack: new JS.Class({\n initialize: function(frame) {\n this._frames = [];\n if (fram"
},
{
"path": "source/fargo/runtime/stackless.js",
"chars": 1623,
"preview": "Fargo.Runtime.extend({\n Stackless: new JS.Class({\n push: function(frame) {\n this._current = frame;\n var Fr"
},
{
"path": "source/fargo/runtime/top_level.js",
"chars": 679,
"preview": "Fargo.Runtime.extend({\n TopLevel: new JS.Class(Fargo.Runtime.Scope, {\n initialize: function() {\n this.callSuper"
},
{
"path": "source/fargo/runtime/value.js",
"chars": 122,
"preview": "Fargo.Runtime.extend({\n Value: new JS.Class({\n initialize: function(value) {\n this.value = value;\n }\n })\n})"
},
{
"path": "source/fargo/scheme.js",
"chars": 103437,
"preview": "\n(function() {;\n var namespace = this;\n namespace = namespace.Fargo = namespace.Fargo || {};\n if (typeof export"
},
{
"path": "source/fargo/scheme.peg",
"chars": 1162,
"preview": "grammar Fargo.Scheme\n \n program <- shebang? cell* <Fargo.Scheme.Program>\n \n shebang <- space* \"#!\" (![\\n\\r] .)*\n"
},
{
"path": "source/fargo/scheme_nodes.js",
"chars": 2466,
"preview": "Fargo.Scheme.Program = new JS.Module({\n eval: function(scope) {\n var expr = this.convert(),\n value = null,\n "
},
{
"path": "source/fargo.js",
"chars": 2404,
"preview": "Fargo = new JS.Module('Fargo');\n\nFargo.extend({\n VERSION: '0.0.1-preview',\n \n Runtime: new JS.Class({\n initialize:"
},
{
"path": "test.js",
"chars": 1565,
"preview": "var path = require('path'),\n assert = require('assert'),\n sys = require('sys');\n\nJSCLASS_PATH = './build/js.c"
},
{
"path": "try-fargo/analytics.js",
"chars": 413,
"preview": "var _gaq = _gaq || [];\n_gaq.push(['_setAccount', 'UA-873493-9']);\n_gaq.push(['_trackPageview']);\n\n(function() {\n var ga"
},
{
"path": "try-fargo/index.html",
"chars": 3912,
"preview": "<!doctype html>\n<html>\n <head>\n <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\n <title>Try F"
},
{
"path": "try-fargo/javascripts/packages.js",
"chars": 370,
"preview": "JS.Packages(function() { with(this) {\n file('/javascripts/fargo/fargo-min.js')\n .provides('Fargo')\n .requires('JS"
},
{
"path": "try-fargo/style.css",
"chars": 1063,
"preview": "html {\n background: #ddf2fd;\n background-image: -webkit-gradient(radial, 50% 40%, 5, 40% 40%, 800, from(#ddf2fd), to(#"
}
]
About this extraction
This page contains the full source code of the jcoglan/fargo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (161.7 KB), approximately 37.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.