├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── LICENSE
├── README.md
├── console.html
├── console.js
├── lib
├── builtin
│ ├── args.js
│ ├── array.js
│ ├── boolean.js
│ ├── date.js
│ ├── error.js
│ ├── func.js
│ ├── global.js
│ ├── hosted
│ │ ├── array.js
│ │ ├── error.js
│ │ ├── global.js
│ │ ├── math.js
│ │ ├── number.js
│ │ ├── object.js
│ │ ├── regexp.js
│ │ └── string.js
│ ├── impl
│ │ ├── args.js
│ │ ├── array.js
│ │ ├── boolean.js
│ │ ├── date.js
│ │ ├── error.js
│ │ ├── func.js
│ │ ├── global.js
│ │ ├── math.js
│ │ ├── native_errors.js
│ │ ├── number.js
│ │ ├── object.js
│ │ ├── regexp.js
│ │ └── string.js
│ ├── math.js
│ ├── meta
│ │ ├── args.js
│ │ ├── array.js
│ │ ├── base.js
│ │ ├── boolean.js
│ │ ├── bound_function.js
│ │ ├── builtin_constructor.js
│ │ ├── builtin_function.js
│ │ ├── date.js
│ │ ├── error.js
│ │ ├── func.js
│ │ ├── language_function.js
│ │ ├── number.js
│ │ ├── object.js
│ │ ├── primitive_box.js
│ │ ├── regexp.js
│ │ └── string.js
│ ├── native_errors.js
│ ├── number.js
│ ├── object.js
│ ├── operations
│ │ ├── args.js
│ │ ├── array.js
│ │ ├── boolean.js
│ │ ├── builtin_constructor.js
│ │ ├── builtin_function.js
│ │ ├── global.js
│ │ ├── language_function.js
│ │ ├── number.js
│ │ ├── object.js
│ │ ├── regexp.js
│ │ └── string.js
│ ├── regexp.js
│ └── string.js
├── completion.js
├── compute.js
├── compute
│ ├── cont.js
│ ├── context.js
│ ├── io.js
│ ├── program.js
│ ├── statement.js
│ └── tail.js
├── context
│ ├── environment.js
│ ├── environment_record.js
│ ├── environment_reference.js
│ ├── execution_context.js
│ ├── execution_metadata.js
│ ├── execution_settings.js
│ ├── property_reference.js
│ └── stack_frame.js
├── external
│ └── importScripts.js
├── fun.js
├── internal_reference.js
├── interpret.js
├── iref.js
├── operations
│ ├── boolean.js
│ ├── compare.js
│ ├── construct.js
│ ├── declaration_binding.js
│ ├── environment.js
│ ├── error.js
│ ├── evaluation.js
│ ├── execution_context.js
│ ├── execution_settings.js
│ ├── func.js
│ ├── internal_reference.js
│ ├── iref.js
│ ├── nil.js
│ ├── number.js
│ ├── object.js
│ ├── property.js
│ ├── string.js
│ ├── type_conversion.js
│ ├── undef.js
│ └── value_reference.js
├── reference.js
├── semantics
│ ├── declaration.js
│ ├── expression.js
│ ├── func.js
│ ├── program.js
│ ├── semantics.js
│ ├── statement.js
│ └── value.js
├── value
│ ├── args.js
│ ├── boolean.js
│ ├── compare.js
│ ├── math.js
│ ├── nil.js
│ ├── number.js
│ ├── object.js
│ ├── property.js
│ ├── regexp.js
│ ├── string.js
│ ├── type.js
│ ├── type_conversion.js
│ ├── undef.js
│ └── value.js
└── value_reference.js
├── package.json
├── resources
├── codemirror-3.14
│ ├── codemirror.css
│ ├── codemirror.js
│ └── javascript.js
├── jquery-1.8.3.min.js
├── require.js
└── text.js
├── server.js
└── test
├── $.js
├── builtin
├── testArguments.js
├── testBoolean.js
├── testBuiltins.js
├── testFunction.js
├── testNumber.js
├── testObject.js
└── testString.js
├── expect.js
├── index.html
├── resources
├── qunit-1.9.0.css
└── qunit-1.9.0.js
├── testArray.js
├── testCompare.js
├── testEnvironment.js
├── testFor.js
├── testForIn.js
├── testFunc.js
├── testIf.js
├── testIn.js
├── testIncDec.js
├── testInheritance.js
├── testInstanceof.js
├── testLogical.js
├── testNumber.js
├── testObject.js
├── testString.js
├── testSwitch.js
├── testTry.js
├── testUnary.js
├── testWhile.js
└── testWith.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project Files #
2 | #################
3 | .project
4 | _*
5 |
6 | # OS Files #
7 | ############
8 | .DS_Store*
9 | ehthumbs.db
10 | Icon?
11 | Thumbs.db
12 |
13 | # Temp Files #
14 | ##############
15 | *~
16 | *.tmp*
17 | *.orig
18 | *.cache
19 | *.log
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "dependencies/parse-ecma"]
2 | path = dependencies/parse-ecma
3 | url = https://github.com/mattbierner/parse-ecma
4 | [submodule "dependencies/parse"]
5 | path = dependencies/parse
6 | url = https://github.com/mattbierner/parse.js
7 | [submodule "dependencies/amulet"]
8 | path = dependencies/amulet
9 | url = https://github.com/mattbierner/amulet.git
10 | [submodule "dependencies/nu"]
11 | path = dependencies/nu
12 | url = https://github.com/mattbierner/nu.git
13 | [submodule "dependencies/ecma-ast"]
14 | path = dependencies/ecma-ast
15 | url = https://github.com/mattbierner/ecma-ast.git
16 | [submodule "dependencies/seshat"]
17 | path = dependencies/seshat
18 | url = https://github.com/mattbierner/seshat.git
19 | [submodule "dependencies/bennu"]
20 | path = dependencies/bennu
21 | url = https://github.com/mattbierner/bennu.git
22 | [submodule "dependencies/seshet"]
23 | path = dependencies/seshet
24 | url = https://github.com/mattbierner/seshet.git
25 | [submodule "dependencies/bes"]
26 | path = dependencies/bes
27 | url = https://github.com/mattbierner/bes.git
28 | [submodule "dependencies/hamt"]
29 | path = dependencies/hamt
30 | url = https://github.com/mattbierner/hamt.git
31 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # ChangeLog #
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (C) 2013 Matt Bierner
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
--------------------------------------------------------------------------------
/console.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Atum
6 |
7 |
8 |
9 |
100 |
101 |
102 |
103 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
121 |
122 |
123 |
124 |
125 |
126 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/console.js:
--------------------------------------------------------------------------------
1 | require(['atum/interpret',
2 | 'atum/compute',
3 | 'atum/compute/context',
4 | 'atum/builtin/impl/global',
5 | 'atum/builtin/operations/global',
6 | 'atum/operations/evaluation',
7 | 'atum/semantics/semantics',
8 | 'ecma/parse/parser'],
9 | function(interpret,
10 | compute,
11 | context,
12 | global,
13 | global_operations,
14 | evaluation) {
15 |
16 | /*
17 | ******************************************************************************/
18 | var out = {
19 | 'write': function(x, ctx) {
20 | $('#output-console').append("" +
21 | x +
22 | "");
23 | }
24 | };
25 |
26 | var errorOut = {
27 | 'write': function(x, ctx) {
28 | $('#output-console').append("" +
29 | x +
30 | "");
31 | }
32 | };
33 |
34 | var run = function (input, ok, err) {
35 | console.profile();
36 | return interpret.exec(
37 | evaluation.evaluateText(input),
38 | globalCtx,
39 | function(x, ctx) {
40 | console.profileEnd();
41 | return ok(x, ctx);
42 | },
43 | function(x, ctx) {
44 | console.profileEnd();
45 | return err(x, ctx);
46 | },
47 | err);
48 | };
49 |
50 | /* Code Mirror
51 | ******************************************************************************/
52 | var doc = CodeMirror(document.getElementById('input'), {
53 | 'mode': 'javascript',
54 | 'lineNumbers': true
55 | }).doc;
56 |
57 | /*
58 | ******************************************************************************/
59 | var globalCtx = interpret.exec(
60 | compute.sequence(
61 | global.initialize(),
62 | global_operations.enterGlobal(),
63 | compute.computeContext),
64 | context.ComputeContext.empty,
65 | function(x) { return x },
66 | function(x) { return x });
67 |
68 | $(function(){
69 | $('button#eval-button').on('click', function(e){
70 | run(doc.getValue(), out.write, errorOut.write);
71 | });
72 | });
73 |
74 | });
75 |
--------------------------------------------------------------------------------
/lib/builtin/args.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Arguments References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Arguments': vr.create('Arguments'),
12 |
13 | 'strictCalleeThrower': vr.create('Arguments callee thrower'),
14 | 'strictCallerThrower': vr.create('Arguments caller thrower')
15 | };
16 |
17 | });
--------------------------------------------------------------------------------
/lib/builtin/array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Array References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Array': vr.create('Array'),
12 | 'ArrayIsArray': vr.create('Array.isArray'),
13 |
14 | 'ArrayPrototype': vr.create('Array.prototype')
15 | };
16 |
17 | });
--------------------------------------------------------------------------------
/lib/builtin/boolean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Boolean Object References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Boolean': vr.create('Boolean'),
12 |
13 | 'BooleanPrototype': vr.create('Boolean.prototype'),
14 | 'BooleanPrototypeToString': vr.create('Boolean.prototype.toString'),
15 | 'BooleanPrototypeValueOf': vr.create('Boolean.prototype.valueOf')
16 | };
17 |
18 | });
--------------------------------------------------------------------------------
/lib/builtin/date.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Date References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Date': vr.create('Date'),
12 | 'DateParse': vr.create('Date.parse'),
13 | 'DateUTC': vr.create('Date.UTC'),
14 | 'DateNow': vr.create('Date.now'),
15 |
16 | 'DatePrototype': vr.create('Date.prototype'),
17 | 'DatePrototypeToString': vr.create('Date.prototype.toString'),
18 | 'DatePrototypeToDateString': vr.create('Date.prototype.toDateString'),
19 | 'DatePrototypeToTimeString': vr.create('Date.prototype.toTimeString'),
20 | 'DatePrototypeToLocaleString': vr.create('Date.prototype.toLocaleString'),
21 | 'DatePrototypeToLocaleDateString': vr.create('Date.prototype.toLocaleDateString'),
22 | 'DatePrototypeLocaleTimeString': vr.create('Date.prototype.toLocaleTimeString'),
23 | 'DatePrototypeToUTCString': vr.create('Date.prototype.toUTCString'),
24 | 'DatePrototypeToISOString': vr.create('Date.prototype.toISOString'),
25 |
26 | 'DatePrototypeValueOf': vr.create('Date.prototype.valueOf'),
27 | 'DatePrototypeToJSON': vr.create('Date.prototype.toJSON'),
28 |
29 | 'DatePrototypeGetTimezoneOffset': vr.create('Date.prototype.getTimezoneOffset'),
30 |
31 | 'DatePrototypeGetFullYear': vr.create('Date.prototype.getFullYear'),
32 | 'DatePrototypeSetFullYear': vr.create('Date.prototype.setFullYear'),
33 |
34 | 'DatePrototypeGetUTCFullYear': vr.create('Date.prototype.getUTCFullYear'),
35 | 'DatePrototypeSetUTCFullYear': vr.create('Date.prototype.setUTCFullYear'),
36 |
37 | 'DatePrototypeGetDate': vr.create('Date.prototype.getDate'),
38 | 'DatePrototypeSetDate': vr.create('Date.prototype.setDate'),
39 |
40 | 'DatePrototypeGetUTCDate': vr.create('Date.prototype.getUTCDate'),
41 | 'DatePrototypeSetUTCDate': vr.create('Date.prototype.setUTCDate'),
42 |
43 | 'DatePrototypeGetMonth': vr.create('Date.prototype.getMonth'),
44 | 'DatePrototypeSetMonth': vr.create('Date.prototype.setMonth'),
45 |
46 | 'DatePrototypeGetUTCMonth': vr.create('Date.prototype.getUTCMonth'),
47 | 'DatePrototypeSetUTCMonth': vr.create('Date.prototype.setUTCMonth'),
48 |
49 | 'DatePrototypeGetTime': vr.create('Date.prototype.getTime'),
50 | 'DatePrototypeSetTime': vr.create('Date.prototype.setTime'),
51 |
52 | 'DatePrototypeGetUTCTime': vr.create('Date.prototype.getUTCTime'),
53 | 'DatePrototypeSetUTCTime': vr.create('Date.prototype.setUTCTime'),
54 |
55 | 'DatePrototypeGetDay': vr.create('Date.prototype.getDay'),
56 |
57 | 'DatePrototypeGetUTCDay': vr.create('Date.prototype.getUTCDay'),
58 |
59 | 'DatePrototypeGetHours': vr.create('Date.prototype.getHours'),
60 | 'DatePrototypeSetHours': vr.create('Date.prototype.setHours'),
61 |
62 | 'DatePrototypeGetUTCHours': vr.create('Date.prototype.getUTCHours'),
63 | 'DatePrototypeSetUTCHours': vr.create('Date.prototype.setUTCHours'),
64 |
65 | 'DatePrototypeGetMinutes': vr.create('Date.prototype.getMinutes'),
66 | 'DatePrototypeSetMinutes': vr.create('Date.prototype.setMinutes'),
67 |
68 | 'DatePrototypeGetUTCMinutes': vr.create('Date.prototype.getUTCMinutes'),
69 | 'DatePrototypeSetUTCMinutes': vr.create('Date.prototype.setUTCMinutes'),
70 |
71 | 'DatePrototypeGetSeconds': vr.create('Date.prototype.getSeconds'),
72 | 'DatePrototypeSetSeconds': vr.create('Date.prototype.setSeconds'),
73 |
74 | 'DatePrototypeGetUTCSeconds': vr.create('Date.prototype.getUTCSeconds'),
75 | 'DatePrototypeSetUTCSeconds': vr.create('Date.prototype.setUTCSeconds'),
76 |
77 | 'DatePrototypeGetMilliseconds': vr.create('Date.prototype.getMilliseconds'),
78 | 'DatePrototypeSetMilliseconds': vr.create('Date.prototype.setMilliseconds'),
79 |
80 | 'DatePrototypeGetUTCMilliseconds': vr.create('Date.prototype.getUTCMilliseconds'),
81 | 'DatePrototypeSetUTCMilliseconds': vr.create('Date.prototype.setUTCMilliseconds')
82 | };
83 |
84 | });
--------------------------------------------------------------------------------
/lib/builtin/error.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Error References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Error': vr.create('Error'),
12 |
13 | 'ErrorPrototype': vr.create('Error.prototype')
14 | };
15 |
16 | });
--------------------------------------------------------------------------------
/lib/builtin/func.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Function References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Function': vr.create('Function'),
12 |
13 | 'FunctionPrototype': vr.create('Function.prototype'),
14 | 'FunctionPrototypeApply': vr.create('Function.prototype.apply'),
15 | 'FunctionPrototypeBind': vr.create('Function.prototype.bind'),
16 | 'FunctionPrototypeCall': vr.create('Function.prototype.call')
17 | };
18 |
19 | });
--------------------------------------------------------------------------------
/lib/builtin/global.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Global References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'global': vr.create('global'),
12 |
13 | 'globalEval': vr.create('eval'),
14 | 'globalParseInt': vr.create('parseInt'),
15 | 'globalParseFloat': vr.create('parseFloat'),
16 | 'globalDecodeURI': vr.create('decodeURI'),
17 | 'globalDecodeURIComponent': vr.create('decodeURIComponent'),
18 | 'globalEncodeURI': vr.create('globalEncodeURI'),
19 | 'globalEncodeURIComponent': vr.create('encodeURIComponent')
20 | };
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/lib/builtin/hosted/error.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Error builtins defined in the hosted language.
3 | */
4 | "use strict";
5 |
6 | /**
7 | * `Error.prototype.toString`
8 | */
9 | Object.defineProperty(Error.prototype, 'toString', {
10 | 'value': function(x) {
11 | var o = this;
12 | if (!(o instanceof Object))
13 | throw TypeError("Error.prototype.toString called on: " + o);
14 |
15 | var name = o.name;
16 | if (name === undefined)
17 | name = "Error";
18 | else
19 | name = name + "";
20 |
21 | var msg = o.message;
22 | if (msg === undefined)
23 | msg = "";
24 | else
25 | msg = msg + "";
26 |
27 | if (name === "")
28 | return msg;
29 | else if (msg === "")
30 | return name;
31 | else
32 | return name + ": " + msg;
33 | },
34 | 'enumerable': false,
35 | 'configurable': true,
36 | 'writable': true
37 | });
38 |
--------------------------------------------------------------------------------
/lib/builtin/hosted/global.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Global builtins defined in the hosted language.
3 | */
4 |
5 | /**
6 | * `isNaN(x)`
7 | */
8 | Object.defineProperty(this, 'isNaN', {
9 | 'value': function(x) {
10 | var num = +x;
11 | return (num !== num);
12 | },
13 | 'enumerable': false,
14 | 'configurable': true,
15 | 'writable': true
16 | });
17 |
18 | /**
19 | * `isFinite(x)`
20 | */
21 | Object.defineProperty(this, 'isFinite', {
22 | 'value': function(x) {
23 | var num = +x;
24 | return (!isNaN(num) && num !== Infinity && num !== -Infinity);
25 | },
26 | 'enumerable': false,
27 | 'configurable': true,
28 | 'writable': true
29 | });
30 |
--------------------------------------------------------------------------------
/lib/builtin/hosted/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number builtins defined in the hosted language.
3 | */
4 | "use strict";
5 |
6 | /**
7 | * `Math.max(value1, value2, ...)`
8 | */
9 | Object.defineProperty(Math, 'max', {
10 | 'value': function(value1, value2 /*, ...*/) {
11 | var largest = -Infinity;
12 | for (var i = 0; i < arguments.length; ++i) {
13 | var val = Number(arguments[i]);
14 | if (isNaN(val))
15 | return NaN;
16 | if (val > largest)
17 | largest = val;
18 | }
19 | return largest;
20 | },
21 | 'enumerable': false,
22 | 'configurable': true,
23 | 'writable': true
24 | });
25 |
26 | /**
27 | * `Math.min(value1, value2, ...)`
28 | */
29 | Object.defineProperty(Math, 'min', {
30 | 'value': function(value1, value2 /*, ...*/) {
31 | var smallest = Infinity;
32 | for (var i = 0; i < arguments.length; ++i) {
33 | var val = Number(arguments[i]);
34 | if (isNaN(val))
35 | return NaN;
36 | if (val < smallest)
37 | smallest = val;
38 | }
39 | return smallest;
40 | },
41 | 'enumerable': false,
42 | 'configurable': true,
43 | 'writable': true
44 | });
--------------------------------------------------------------------------------
/lib/builtin/hosted/number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number builtins defined in the hosted language.
3 | */
4 | "use strict";
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lib/builtin/hosted/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Object builtins defined in the hosted language.
3 | */
4 | "use strict";
5 |
6 | var isDataDescriptor = function(desc) {
7 | if (!desc)
8 | return false;
9 | return desc.hasOwnProperty('value') || desc.hasOwnProperty('writable');
10 | };
11 |
12 | /**
13 | * `isFrozen(obj)`
14 | */
15 | Object.defineProperty(Object, 'isFrozen', {
16 | 'value': function isFrozen(obj) {
17 | var type = typeof obj;
18 | if (type !== 'object' && type !== 'function')
19 | throw new TypeError();
20 |
21 | var names = Object.getOwnPropertyNames(obj);
22 | for (var i = 0, len = names.length; i < len; ++i) {
23 | var name = names[i];
24 | var desc = Object.getOwnPropertyDescriptor(obj, name);
25 | if (desc.writable)
26 | return false
27 | }
28 |
29 | return !Object.isExtensible(obj);
30 | },
31 | 'enumerable': false,
32 | 'configurable': true,
33 | 'writable': true
34 | });
35 |
36 | /**
37 | * `Object.freeze(obj)`
38 | */
39 | Object.defineProperty(Object, 'freeze', {
40 | 'value': function freeze(obj) {
41 | var type = typeof obj;
42 | if (type !== 'object' && type !== 'function')
43 | throw new TypeError();
44 |
45 | var names = Object.getOwnPropertyNames(obj);
46 | for (var i = 0, len = names.length; i < len; ++i) {
47 | var name = names[i];
48 | var desc = Object.getOwnPropertyDescriptor(obj, name);
49 | if (isDataDescriptor(desc)) {
50 | if (desc.writable) {
51 | desc.writable = false;
52 | Object.defineProperty(obj, name, desc);
53 | }
54 | }
55 | }
56 | Object.preventExtensions(obj);
57 | return obj;
58 | },
59 | 'enumerable': false,
60 | 'configurable': true,
61 | 'writable': true
62 | });
63 |
64 | /**
65 | * `Object.isSealed(obj)`
66 | */
67 | Object.defineProperty(Object, 'isSealed', {
68 | 'value': function isSealed(obj) {
69 | var type = typeof obj;
70 | if (type !== 'object' && type !== 'function')
71 | throw new TypeError();
72 |
73 | var names = Object.getOwnPropertyNames(obj);
74 | for (var i = 0, len = names.length; i < len; ++i) {
75 | var name = names[i];
76 | var desc = Object.getOwnPropertyDescriptor(obj, name);
77 | if (desc.configurable)
78 | return false
79 | }
80 |
81 | return !Object.isExtensible(obj);
82 | },
83 | 'enumerable': false,
84 | 'configurable': true,
85 | 'writable': true
86 | });
87 |
88 | /**
89 | * `Object.seal(obj)`
90 | */
91 | Object.defineProperty(Object, 'seal', {
92 | 'value': function seal(obj) {
93 | var type = typeof obj;
94 | if (type !== 'object' && type !== 'function')
95 | throw new TypeError();
96 |
97 | var names = Object.getOwnPropertyNames(obj);
98 | for (var i = 0, len = names.length; i < len; ++i) {
99 | var name = names[i];
100 | var desc = Object.getOwnPropertyDescriptor(obj, name);
101 | if (isDataDescriptor(desc)) {
102 | if (desc.configurable) {
103 | desc.configurable = false;
104 | Object.defineProperty(obj, name, desc);
105 | }
106 | }
107 | }
108 | Object.preventExtensions(obj);
109 | return obj;
110 | },
111 | 'enumerable': false,
112 | 'configurable': true,
113 | 'writable': true
114 | });
--------------------------------------------------------------------------------
/lib/builtin/hosted/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number builtins defined in the hosted language.
3 | */
4 | "use strict";
5 |
6 | /**
7 | * `RegExp.prototype.test(string)`
8 | */
9 | Object.defineProperty(RegExp.prototype, 'test', {
10 | 'value': function(string) {
11 | var match = RegExp.prototype.exec.call(this, string);
12 | return (match !== null);
13 | },
14 | 'enumerable': false,
15 | 'configurable': true,
16 | 'writable': true
17 | });
--------------------------------------------------------------------------------
/lib/builtin/impl/args.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Builtin arguments object.
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/builtin/args',
8 | 'atum/builtin/object',
9 | 'atum/builtin/meta/args',
10 | 'atum/builtin/operations/builtin_constructor',
11 | 'atum/builtin/operations/builtin_function',
12 | 'atum/operations/construct',
13 | 'atum/operations/error',
14 | 'atum/operations/value_reference'],
15 | function(exports,
16 | record,
17 | compute,
18 | args_builtin,
19 | object_builtin,
20 | meta_arguments,
21 | builtin_constructor,
22 | builtin_function,
23 | construct,
24 | error,
25 | value_reference){
26 | "use strict";
27 |
28 | /* Arguments
29 | ******************************************************************************/
30 | var Arguments = {
31 | 'call': function(ref, _, args) {
32 | return construct.constructForward(ref, args);
33 | },
34 |
35 | 'construct': function(ref, thisObj, args) {
36 | return value_reference.create(new ArgumentsInstance());
37 | },
38 |
39 | 'properties': {}
40 | };
41 |
42 | /* ArgumentsInstance
43 | ******************************************************************************/
44 | var ArgumentsInstance = record.extend(meta_arguments.Arguments,
45 | [],
46 | function() {
47 | meta_arguments.Arguments.call(this, this.proto, this.properties, true);
48 | });
49 |
50 | ArgumentsInstance.prototype.proto = object_builtin.ObjectPrototype;
51 |
52 | ArgumentsInstance.prototype.properties = {};
53 |
54 | /* Strict Accessors
55 | ******************************************************************************/
56 | var strictCalleeThrower = function(ref, thisObj, args) {
57 | return error.typeError('Cannot accesss arguments callee in strict mode');
58 | };
59 |
60 | var strictCallerThrower = function(ref, thisObj, args) {
61 | return error.typeError('Cannot accesss arguments caller in strict mode');
62 | };
63 |
64 | /* Initialization
65 | ******************************************************************************/
66 | var initialize = function() {
67 | return compute.sequence(
68 | builtin_constructor.create(args_builtin.Arguments, '', 0, Arguments.properties, Arguments.call, Arguments.construct),
69 |
70 | builtin_function.create(args_builtin.strictCalleeThrower, '', 0, strictCalleeThrower),
71 | builtin_function.create(args_builtin.strictCallerThrower, '', 0, strictCallerThrower));
72 | };
73 |
74 | /* Export
75 | ******************************************************************************/
76 | exports.initialize = initialize;
77 |
78 | });
--------------------------------------------------------------------------------
/lib/builtin/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Math References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Math': vr.create('Math'),
12 |
13 | 'MathAcos': vr.create('Math.acos'),
14 | 'MathAsin': vr.create('Math.asin'),
15 | 'MathAtan': vr.create('Math.atan'),
16 | 'MathAtan2': vr.create('Math.atan2'),
17 | 'MathCeil': vr.create('Math.ceil'),
18 | 'MathCos': vr.create('Math.cos'),
19 | 'MathExp': vr.create('Math.exp'),
20 | 'MathFloor': vr.create('Math.floor'),
21 | 'MathLog': vr.create('Math.log'),
22 | 'MathPow': vr.create('Math.pow'),
23 | 'MathRandom': vr.create('Math.random'),
24 | 'MathRound': vr.create('Math.round'),
25 | 'MathSin': vr.create('Math.sin'),
26 | 'MathSqrt': vr.create('Math.sqrt'),
27 | 'MathTan': vr.create('Math.tan')
28 | };
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/args.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Arguments meta object
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/object'],
7 | function(exports,
8 | record,
9 | meta_object){
10 | "use strict";
11 |
12 | /* Arguments
13 | ******************************************************************************/
14 | /**
15 | * Arguments meta
16 | */
17 | var Arguments = record.extend(meta_object.Object, [
18 | 'func',
19 | 'names',
20 | 'args',
21 | 'env',
22 | 'strict']);
23 |
24 | Arguments.prototype.cls = "Arguments";
25 |
26 | /* Export
27 | ******************************************************************************/
28 | exports.Arguments = Arguments;
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Array meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/fun',
8 | 'atum/builtin/meta/object',
9 | 'atum/operations/number',
10 | 'atum/operations/object',
11 | 'atum/value/compare',
12 | 'atum/value/number',
13 | 'atum/value/type_conversion'],
14 | function(exports,
15 | record,
16 | compute,
17 | fun,
18 | meta_object,
19 | number,
20 | object,
21 | compare,
22 | number_value,
23 | type_conversion){
24 | "use strict";
25 |
26 | var isArrayIndex = function(name) {
27 | return !isNaN(name) && +name >= 0;
28 | };
29 |
30 | /* Array
31 | ******************************************************************************/
32 | /**
33 | * Array meta
34 | */
35 | var Array = record.extend(meta_object.Object,
36 | []);
37 |
38 | Array.prototype.cls = "Array";
39 |
40 | Array.prototype.defineOwnProperty = function() {
41 | return meta_object.Object.prototype.defineProperty.apply(this, arguments);
42 | };
43 |
44 | Array.prototype.defineProperty = function(ref, name, desc, strict) {
45 | var self = this;
46 | var oldLenDesc = this.getOwnProperty('length');
47 | var oldLen = oldLenDesc.value.value;
48 |
49 | if (name === 'length')
50 | {
51 | var len = type_conversion.toUint32(desc.value);
52 | if (!compare.strictEqual(len, type_conversion.toNumber(desc.value)))
53 | return error.rangeError();
54 |
55 | var newLenDesc = oldLenDesc.setValue(len);
56 |
57 | if (len.value >= oldLen)
58 | return self.defineOwnProperty(ref, 'length', newLenDesc);
59 |
60 | if (!oldLenDesc.writable)
61 | return error.rangeError();
62 |
63 | return compute.next(
64 | self.defineOwnProperty(ref, 'length', newLenDesc),
65 | compute.mapm_(
66 | fun.curry(object.deleteProperty, ref),
67 | fun.range(oldLen - 1, len.value - 1, -1)));
68 | }
69 | else if (isArrayIndex(name))
70 | {
71 | var index = +name;
72 | if (index >= oldLen && !oldLenDesc.writable)
73 | return compute.error('TODO');
74 |
75 | if (index >= oldLen) {
76 | return compute.next(
77 | self.defineOwnProperty(ref, name, desc),
78 | object.defineProperty(ref, 'length',
79 | oldLenDesc.setValue(number_value.Number.create(index + 1))));
80 | }
81 | }
82 |
83 | return self.defineOwnProperty(ref, name, desc);
84 | };
85 |
86 | /* Export
87 | ******************************************************************************/
88 | exports.Array = Array;
89 |
90 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/boolean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Boolean object meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/primitive_box',
7 | 'atum/value/boolean'],
8 | function(exports,
9 | record,
10 | primitive_box,
11 | boolean){
12 | "use strict";
13 |
14 | /* Boolean
15 | ******************************************************************************/
16 | /**
17 | * Boolean object meta
18 | */
19 | var Boolean = record.extend(primitive_box.PrimitiveBox,
20 | [])
21 |
22 | Boolean.prototype.cls = "Boolean";
23 |
24 | /* Export
25 | ******************************************************************************/
26 | exports.Boolean = Boolean;
27 |
28 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/bound_function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Bound function meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/builtin/meta/func',
8 | 'atum/operations/construct',
9 | 'atum/operations/func',
10 | 'atum/operations/object'],
11 | function(exports,
12 | record,
13 | compute,
14 | meta_func,
15 | construct,
16 | func,
17 | object){
18 | "use strict";
19 |
20 | /* BoundFunction
21 | ******************************************************************************/
22 | /**
23 | * Meta object for a function with bound a this object and set of bound arguments.
24 | *
25 | * @param proto Object prototype.
26 | * @param props Object properties.
27 | * @param extensible Is the object extensible.
28 | * @param target Reference the function being bound.
29 | * @param boundThis The this object used for calling the bound function.
30 | * @param boundArgs Arguments forwarded to the bound function.
31 | */
32 | var BoundFunction = record.extend(meta_func.Function, [
33 | 'target',
34 | 'boundThis',
35 | 'boundArgs']);
36 |
37 | BoundFunction.prototype.construct = function(ref, args) {
38 | return construct.constructForward(
39 | this.target,
40 | this.boundArgs.concat(args));
41 | };
42 |
43 | BoundFunction.prototype.call = function(ref, thisObj, args) {
44 | return func.forward(
45 | this.target,
46 | this.boundThis,
47 | this.boundArgs.concat(args));
48 | };
49 |
50 | BoundFunction.prototype.hasInstance = function(ref, v) {
51 | return object.hasInstance(this.target, v);
52 | };
53 |
54 | /* Export
55 | ******************************************************************************/
56 | exports.BoundFunction = BoundFunction;
57 |
58 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/builtin_constructor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Builtin constructor meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/builtin_function'],
7 | function(exports,
8 | record,
9 | meta_builtin_function){
10 | "use strict";
11 |
12 | /* BuiltinConstructor
13 | ******************************************************************************/
14 | /**
15 | * Meta object for a function included in the hosted language as a builtin.
16 | */
17 | var BuiltinConstructor = record.declare(new meta_builtin_function.BuiltinFunction, [
18 | 'proto',
19 | 'properties',
20 | 'extensible',
21 | '_call',
22 | '_construct'],
23 | function(proto, props, extensible, call, construct) {
24 | meta_builtin_function.BuiltinFunction.call(this, proto, props, extensible, call);
25 | this.construct = construct && construct.bind(this);
26 | this._call = call;
27 | this._construct = construct;
28 | });
29 |
30 | /* Export
31 | ******************************************************************************/
32 | exports.BuiltinConstructor = BuiltinConstructor;
33 |
34 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/builtin_function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Builtin function meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/func'],
7 | function(exports,
8 | record,
9 | meta_func){
10 | "use strict";
11 |
12 | /* BuiltinFunction
13 | ******************************************************************************/
14 | /**
15 | * Meta object for a function included in the hosted language as a builtin.
16 | */
17 | var BuiltinFunction = record.extend(meta_func.Function, [
18 | 'id',
19 | 'impl'],
20 | function(proto, props, extensible, impl) {
21 | meta_func.Function.call(this, proto, props, extensible);
22 | this.impl = impl;
23 | this.call = (impl ? impl.bind(this) : null);
24 | });
25 |
26 | /* Export
27 | ******************************************************************************/
28 | exports.BuiltinFunction = BuiltinFunction;
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/date.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Date meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/object',
7 | 'atum/value/type'],
8 | function(exports,
9 | record,
10 | meta_object,
11 | type){
12 | "use strict";
13 |
14 | /* Date
15 | ******************************************************************************/
16 | /**
17 | * Date object meta
18 | */
19 | var Date = record.extend(meta_object.Object, [
20 | 'primitiveValue'],
21 | function(proto, props, extensible, primitiveValue) {
22 | meta_object.Object.call(this, proto, props, extensible);
23 | this.primitiveValue = primitiveValue;
24 | });
25 |
26 | Date.prototype.preferedType = type.STRING;
27 |
28 |
29 | /* Export
30 | ******************************************************************************/
31 | exports.Date = Date;
32 |
33 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/error.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Error meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/object'],
7 | function(exports,
8 | record,
9 | meta_object){
10 | "use strict";
11 |
12 | /* Error
13 | ******************************************************************************/
14 | /**
15 | * Error meta
16 | */
17 | var Error = record.extend(meta_object.Object, []);
18 |
19 | Error.prototype.cls = "Error";
20 |
21 | /* Export
22 | ******************************************************************************/
23 | exports.Error = Error;
24 |
25 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/func.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Function meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/builtin/object',
8 | 'atum/builtin/meta/base',
9 | 'atum/operations/construct',
10 | 'atum/operations/error',
11 | 'atum/operations/func',
12 | 'atum/operations/object',
13 | 'atum/operations/value_reference',
14 | 'atum/value/value'],
15 | function(exports,
16 | record,
17 | compute,
18 | object_builtin,
19 | meta_base,
20 | construct,
21 | error,
22 | func,
23 | object,
24 | value_reference,
25 | value){
26 | "use strict";
27 |
28 | /* Function
29 | ******************************************************************************/
30 | /**
31 | * Function abstract base meta
32 | */
33 | var Function = record.extend(meta_base.Base,
34 | []);
35 |
36 | Function.prototype.cls = "Function";
37 |
38 | Function.prototype.construct = function(self, args) {
39 | return compute.bind(
40 | value_reference.dereferenceFrom(
41 | object.get(self, 'prototype'),
42 | function(proto, protoRef) {
43 | return construct.create(
44 | (value.isObject(proto) ?
45 | protoRef :
46 | object_builtin.ObjectPrototype),
47 | {},
48 | true);
49 | }),
50 | function(t) {
51 | return value_reference.dereferenceFrom(
52 | func.forward(self, t, args),
53 | function(result, resultRef) {
54 | return compute.just(value.isObject(result) ? resultRef : t);
55 | });
56 | });
57 | };
58 |
59 | /**
60 | * Is `v` an instance of function `ref`.
61 | *
62 | * @param ref Reference to this object.
63 | * @param v Other object.
64 | */
65 | Function.prototype.hasInstance = (function(){
66 | var checkProtoChain = function(v, o) {
67 | if (!v.proto)
68 | return compute.no;
69 | return value_reference.dereference(v.proto, function(v) {
70 | return (v === o ? compute.yes : checkProtoChain(v, o));
71 | });
72 | };
73 |
74 | return function(ref, v) {
75 | return value_reference.dereference(v, function(v) {
76 | if (!value.isObject(v))
77 | return compute.no;
78 | return value_reference.dereferenceFrom(
79 | object.get(ref, 'prototype'),
80 | function(o) {
81 | if (!value.isObject(o))
82 | return error.typeError();
83 | return checkProtoChain(v, o);
84 | });
85 | });
86 | };
87 | }());
88 |
89 | /* Export
90 | ******************************************************************************/
91 | exports.Function = Function;
92 |
93 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/language_function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Language function meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/fun',
8 | 'atum/builtin/meta/func',
9 | 'atum/operations/declaration_binding',
10 | 'atum/operations/environment',
11 | 'atum/operations/execution_context',
12 | 'atum/operations/func',
13 | 'atum/operations/type_conversion',
14 | 'atum/operations/value_reference',
15 | 'atum/value/type',
16 | 'atum/value/value',],
17 | function(exports,
18 | record,
19 | compute,
20 | fun,
21 | meta_func,
22 | declaration_bindings,
23 | environment,
24 | execution_context,
25 | func,
26 | type_conversion,
27 | value_reference,
28 | type,
29 | value){
30 | "use strict";
31 |
32 | /* LanguageFunction
33 | ******************************************************************************/
34 | /**
35 | * Meta object for a hosted language function defined in code.
36 | */
37 | var LanguageFunction = record.extend(meta_func.Function, [
38 | 'scope',
39 | 'strict',
40 | 'id',
41 | 'names',
42 | 'code',
43 | 'declarations',
44 | 'body']);
45 |
46 | LanguageFunction.prototype._call = function(ref, thisObj, args) {
47 | var self = this;
48 | return environment.environmentBlock(
49 | compute.sequence(
50 | compute.bind(
51 | environment.createDeclativeEnvironment(self.scope),
52 | function(env) {
53 | return declaration_bindings.initFunction(env,
54 | self.strict,
55 | ref,
56 | self.id,
57 | self.names,
58 | args,
59 | self.declarations);
60 | }),
61 | execution_context.withThisBinding(thisObj,
62 | self.body)));
63 | };
64 |
65 | LanguageFunction.prototype.call = function(ref, thisObj, args) {
66 | var self = this, strict = this.strict;
67 | return value_reference.dereference(thisObj, function(t, thisObj) {
68 | if (!strict && !value.isObject(t)) {
69 | switch (t.type) {
70 | case type.UNDEFINED:
71 | case type.NULL:
72 | return compute.bind(
73 | execution_context.thisBinding,
74 | function(t) {
75 | return self._call(ref, t, args);
76 | });
77 |
78 | case type.STRING:
79 | case type.NUMBER:
80 | case type.BOOLEAN:
81 | return compute.bind(
82 | type_conversion.toObject(thisObj),
83 | function(t) {
84 | return func.forward(ref, t, args);
85 | });
86 | }
87 | }
88 | return self._call(ref, thisObj, args);
89 | });
90 | };
91 |
92 | /* Export
93 | ******************************************************************************/
94 | exports.LanguageFunction = LanguageFunction;
95 |
96 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number object meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/primitive_box',
7 | 'atum/value/number'],
8 | function(exports,
9 | record,
10 | primitive_box,
11 | number){
12 | "use strict";
13 |
14 | /* Number
15 | ******************************************************************************/
16 | /**
17 | * Number object meta
18 | */
19 | var Number = record.extend(primitive_box.PrimitiveBox,
20 | []);
21 |
22 | Number.prototype.cls = "Number";
23 |
24 | /* Export
25 | ******************************************************************************/
26 | exports.Number = Number;
27 |
28 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Object meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/base'],
7 | function(exports,
8 | record,
9 | meta_base){
10 | "use strict";
11 |
12 | /* Object
13 | ******************************************************************************/
14 | /**
15 | * Object meta
16 | */
17 | var Object = record.extend(meta_base.Base, []);
18 |
19 | Object.prototype.cls = "Object";
20 |
21 | /* Export
22 | ******************************************************************************/
23 | exports.Object = Object;
24 |
25 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/primitive_box.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Primitive Box meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/builtin/meta/object'],
8 | function(exports,
9 | record,
10 | compute,
11 | meta_object){
12 | "use strict";
13 |
14 | /* PrimitiveBox
15 | ******************************************************************************/
16 | /**
17 | * Boxed primitive value abstract base object meta
18 | */
19 | var PrimitiveBox = record.extend(meta_object.Object, [
20 | 'primitiveValue']);
21 |
22 | PrimitiveBox.prototype.defaultValue = function() {
23 | return compute.just(this.primitiveValue);
24 | };
25 |
26 | /* Export
27 | ******************************************************************************/
28 | exports.PrimitiveBox = PrimitiveBox;
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Regular expression object meta
3 | */
4 | var HostRegExp = RegExp;
5 |
6 | define(['exports',
7 | 'bes/record',
8 | 'atum/builtin/meta/object',
9 | 'atum/value/boolean',
10 | 'atum/value/property',
11 | 'atum/value/string'],
12 | function(exports,
13 | record,
14 | meta_object,
15 | boolean,
16 | property,
17 | string){
18 | "use strict";
19 |
20 | /* RegExp
21 | ******************************************************************************/
22 | /**
23 | * Regular expression object meta
24 | */
25 | var RegExp = record.extend(meta_object.Object, [
26 | 'pattern'],
27 | function(proto, props, extensible, pattern) {
28 | meta_object.Object.call(this, proto, props, extensible);
29 | this.pattern = pattern;
30 | });
31 |
32 | RegExp.prototype.cls = "RegExp";
33 |
34 | Object.defineProperty(RegExp.prototype, 'regExp', {
35 | 'get': function() {
36 | return new HostRegExp(this.pattern.body, this.pattern.flags);
37 | }
38 | });
39 |
40 | RegExp.prototype.getOwnPropertyNames = function() {
41 | return meta_object.Object.prototype.getOwnPropertyNames.call(this)
42 | .concat(
43 | 'source',
44 | 'global',
45 | 'ignoreCase',
46 | 'multiline');
47 | };
48 |
49 | RegExp.prototype.getOwnProperty = function(name) {
50 | var desc = meta_object.Object.prototype.getOwnProperty.call(this, name);
51 | if (desc)
52 | return desc;
53 |
54 | switch (name) {
55 | case 'source':
56 | return property.createValuePropertyFlags(
57 | new string.String(this.pattern.body));
58 | case 'global':
59 | return property.createValuePropertyFlags(
60 | new boolean.Boolean(this.pattern.flags.indexOf('g') !== -1));
61 | case 'ignoreCase':
62 | return property.createValuePropertyFlags(
63 | new boolean.Boolean(this.pattern.flags.indexOf('i') !== -1));
64 | case 'multiline':
65 | return property.createValuePropertyFlags(
66 | new boolean.Boolean(this.pattern.flags.indexOf('m') !== -1));
67 | default:
68 | return null;
69 | }
70 | };
71 |
72 |
73 | /* Export
74 | ******************************************************************************/
75 | exports.RegExp = RegExp;
76 |
77 | });
--------------------------------------------------------------------------------
/lib/builtin/meta/string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview String object meta
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/builtin/meta/primitive_box',
7 | 'atum/value/property',
8 | 'atum/value/string'],
9 | function(exports,
10 | record,
11 | primitive_box,
12 | property,
13 | string){
14 | "use strict";
15 |
16 | var isStringIndex = function(name) {
17 | return !isNaN(name) && +name >= 0 && "" + Math.abs(Math.round(name)) === name;
18 | };
19 |
20 | /* String
21 | ******************************************************************************/
22 | /**
23 | * String object meta
24 | */
25 | var String = record.extend(primitive_box.PrimitiveBox,
26 | []);
27 |
28 | String.prototype.cls = "String";
29 |
30 | String.prototype.getOwnPropertyNames = function() {
31 | return primitive_box.PrimitiveBox.prototype.getOwnPropertyNames.call(this)
32 | .concat(
33 | string.indicies(this.primitiveValue),
34 | 'length');
35 | };
36 |
37 | String.prototype.getOwnProperty = function(name) {
38 | var desc = primitive_box.PrimitiveBox.prototype.getOwnProperty.call(this, name);
39 | if (desc)
40 | return desc;
41 |
42 | if (name === 'length') {
43 | return property.createValuePropertyFlags(
44 | string.length(this.primitiveValue));
45 | } else if (isStringIndex(name)) {
46 | var len = this.primitiveValue.value.length;
47 | if (name < len)
48 | return property.createValuePropertyFlags(
49 | string.charAt(this.primitiveValue, name),
50 | property.ENUMERABLE);
51 | }
52 | return null;
53 | };
54 |
55 | /* Export
56 | ******************************************************************************/
57 | exports.String = String;
58 |
59 | });
--------------------------------------------------------------------------------
/lib/builtin/native_errors.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Native Error References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'EvalError': vr.create('EvalError'),
12 | 'EvalErrorPrototype': vr.create('EvalError.prototype'),
13 |
14 | 'RangeError': vr.create('RangeError'),
15 | 'RangeErrorPrototype': vr.create('RangeError.prototype'),
16 |
17 | 'ReferenceError': vr.create('ReferenceError'),
18 | 'ReferenceErrorPrototype': vr.create('ReferenceError.prototype'),
19 |
20 | 'SyntaxError': vr.create('SyntaxError'),
21 | 'SyntaxErrorPrototype': vr.create('SyntaxError.prototype'),
22 |
23 | 'TypeError': vr.create('TypeError'),
24 | 'TypeErrorPrototype': vr.create('TypeError.prototype'),
25 |
26 | 'UriError': vr.create('UriError'),
27 | 'UriErrorPrototype': vr.create('UriError.prototype')
28 | };
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Number Object References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Number': vr.create('Number'),
12 |
13 | 'NumberPrototype': vr.create('Number.prototype'),
14 | 'NumberPrototypeToExponential': vr.create('Number.prototype.toExponential'),
15 | 'NumberPrototypeToFixed': vr.create('Number.prototype.toFixed'),
16 | 'NumberPrototypeToPrecision': vr.create('Number.prototype.toPrecision'),
17 | 'NumberPrototypeToString': vr.create('Number.prototype.toString'),
18 | 'NumberPrototypeValueOf': vr.create('Number.prototype.valueOf')
19 | };
20 |
21 | });
--------------------------------------------------------------------------------
/lib/builtin/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin Object References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'Object': vr.create('Object'),
12 | 'ObjectCreate': vr.create('Object.create'),
13 | 'ObjectDefineProperty': vr.create('Object.defineProperty'),
14 | 'ObjectDefineProperties': vr.create('Object.defineProperties'),
15 | 'ObjectGetOwnPropertyDescriptor': vr.create('Object.getOwnPropertyDescriptor'),
16 | 'ObjectGetOwnPropertyNames': vr.create('Object.getOwnPropertyNames'),
17 | 'ObjectGetPrototypeOf': vr.create('Object.getPrototypeOf'),
18 | 'ObjectKeys': vr.create('Object.keys'),
19 | 'ObjectIsExtensible': vr.create('Object.isExtensible'),
20 | 'ObjectPreventExtensions': vr.create('Object.preventExtensions'),
21 |
22 | 'ObjectPrototype': vr.create('Object.prototype'),
23 | 'ObjectPrototypeHasOwnProperty': vr.create('Object.prototype.hasOwnProperty'),
24 | 'ObjectPrototypeIsPrototypeOf': vr.create('Object.prototype.isPrototypeOf'),
25 | 'ObjectPrototypePropertyIsEnumerable': vr.create('Object.prototype.propertyIsEnumerable'),
26 | 'ObjectPrototypeToString': vr.create('Object.prototype.toString'),
27 | 'ObjectPrototypeValueOf': vr.create('Object.prototype.valueOf')
28 | };
29 |
30 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Common builtin Array operations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/builtin/array',
8 | 'atum/operations/construct',
9 | 'atum/operations/number',
10 | 'atum/operations/object',
11 | 'atum/value/number',
12 | 'atum/value/property'],
13 | function(exports,
14 | compute,
15 | fun,
16 | array,
17 | construct,
18 | number,
19 | object,
20 | number_value,
21 | property){
22 | "use strict";
23 |
24 | /* Operations
25 | ******************************************************************************/
26 | /**
27 | * Create a new builtin array from a list of elements.
28 | *
29 | * Elements may be null for uninitialized array values.
30 | */
31 | var create = function(elements) {
32 | return compute.bind(
33 | construct.construct(
34 | array.Array,
35 | [new number_value.Number(elements.length)]),
36 | function(t) {
37 | return compute.next(
38 | compute.mapm_(
39 | function(c, i) {
40 | return (!c ? compute.empty :
41 | compute.bind(c, function(x) {
42 | return object.defineProperty(t, i,
43 | property.createValuePropertyFlags(x, property.ALL));
44 | }));
45 | },
46 | elements),
47 | compute.just(t));
48 | });
49 | };
50 |
51 | /**
52 | * Convert a hosted array object to a host array.
53 | */
54 | var toHost = function(arr) {
55 | return compute.bind(
56 | compute.bind(object.get(arr, 'length'), number.toHost),
57 | function(len) {
58 | return compute.eager(compute.mapm(
59 | fun.curry(object.get, arr),
60 | fun.gen(len)));
61 | });
62 | };
63 |
64 | /* Export
65 | ******************************************************************************/
66 | exports.create = create;
67 | exports.toHost = toHost;
68 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/boolean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Boolean builtin operations
3 | */
4 | define(['exports',
5 | 'atum/builtin/boolean',
6 | 'atum/operations/construct'],
7 | function(exports,
8 | builtin_boolean,
9 | construct){
10 | "use strict";
11 |
12 | /* Operations
13 | ******************************************************************************/
14 | /**
15 | * Create a new builtin boolean object
16 | *
17 | * @param primitiveValue Value stored in boolean object.
18 | */
19 | var create = function(primitiveValue) {
20 | return construct.construct(builtin_boolean.Boolean, [primitiveValue]);
21 | };
22 |
23 | /* Export
24 | ******************************************************************************/
25 | exports.create = create;
26 |
27 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/builtin_constructor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Operations for builtin constructors
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/builtin/func',
7 | 'atum/builtin/meta/builtin_constructor',
8 | 'atum/operations/object',
9 | 'atum/value/number',
10 | 'atum/value/string',
11 | 'atum/value/property'],
12 | function(exports,
13 | compute,
14 | func_builtin,
15 | meta_builtin_constructor,
16 | object,
17 | number_value,
18 | string_value,
19 | property){
20 | "use strict";
21 |
22 | /* Operations
23 | ******************************************************************************/
24 | /**
25 | */
26 | var create = function(ref, id, length, properties, call, construct) {
27 | return compute.next(
28 | ref.setValue(
29 | meta_builtin_constructor.BuiltinConstructor.create(
30 | func_builtin.FunctionPrototype,
31 | properties,
32 | true,
33 | call,
34 | construct)),
35 | object.defineProperties(ref, {
36 | 'length': property.createValuePropertyFlags(
37 | number_value.Number.create(length)),
38 |
39 | 'name': property.createValuePropertyFlags(
40 | (id ? string_value.String.create(id) : string_value.EMPTY))
41 | }));
42 | };
43 |
44 | /* Export
45 | ******************************************************************************/
46 | exports.create = create;
47 |
48 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/builtin_function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Hosted function object for functions defined in the host
3 | * language.
4 | */
5 | define(['exports',
6 | 'atum/compute',
7 | 'atum/builtin/func',
8 | 'atum/builtin/meta/builtin_function',
9 | 'atum/operations/object',
10 | 'atum/value/number',
11 | 'atum/value/string',
12 | 'atum/value/property'],
13 | function(exports,
14 | compute,
15 | func_builtin,
16 | meta_builtin_function,
17 | object,
18 | number_value,
19 | string_value,
20 | property){
21 | "use strict";
22 |
23 | /* BuiltinFunction
24 | ******************************************************************************/
25 | /**
26 | * Create a new builtin function.
27 | *
28 | * @param {ref} Value reference the builtin function is being created on.
29 | * @param {string} id Identifier for function.
30 | * @param {number} length Number of arguments the function expects.
31 | * @param impl Host function providing the hosted function's implementation.
32 | */
33 | var create = function(ref, id, length, impl) {
34 | return compute.next(
35 | ref.setValue(meta_builtin_function.BuiltinFunction.create(
36 | func_builtin.FunctionPrototype,
37 | {},
38 | true,
39 | impl)),
40 | object.defineProperties(ref, {
41 | 'length': property.createValuePropertyFlags(
42 | number_value.Number.create(length)),
43 |
44 | 'name': property.createValuePropertyFlags(
45 | (id ? string_value.String.create(id) : string_value.EMPTY))
46 | }));
47 | };
48 |
49 | /* Export
50 | ******************************************************************************/
51 | exports.create = create;
52 |
53 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/global.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Global environment operations.
3 | */
4 | define(['atum/compute',
5 | 'atum/builtin/global',
6 | 'atum/context/execution_context',
7 | 'atum/context/execution_settings',
8 | 'atum/operations/environment',
9 | 'atum/operations/execution_context'],
10 | function(compute,
11 | global_builtin,
12 | execution_context,
13 | execution_settings,
14 | environment,
15 | execution_context_operations) {
16 | "use strict";
17 |
18 | var globalExecutionContext = function(env, obj) {
19 | return execution_context.createGlobalContext(
20 | execution_settings.DEFAULTS,
21 | env,
22 | obj);
23 | };
24 |
25 | /* Operations
26 | ******************************************************************************/
27 | /**
28 | * Create a new global execution context using the global object.
29 | */
30 | var createGlobal = compute.map(
31 | environment.createObjectEnvironment(global_builtin.global, null),
32 | function(lex) {
33 | return globalExecutionContext(lex, global_builtin.global);
34 | });
35 |
36 | /**
37 | * Sets the current execution context to a new global execution context.
38 | */
39 | var enterGlobal = function() {
40 | return compute.bind(
41 | createGlobal,
42 | execution_context_operations.setContext);
43 | };
44 |
45 | /* Export
46 | ******************************************************************************/
47 | return {
48 | 'enterGlobal': enterGlobal
49 | };
50 |
51 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/language_function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Language function operations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/builtin/func',
7 | 'atum/builtin/meta/language_function',
8 | 'atum/builtin/operations/object',
9 | 'atum/operations/construct',
10 | 'atum/operations/func',
11 | 'atum/operations/object',
12 | 'atum/operations/value_reference',
13 | 'atum/value/number',
14 | 'atum/value/string',
15 | 'atum/value/property'],
16 | function(exports,
17 | compute,
18 | func_builtin,
19 | meta_language_function,
20 | object_builtin,
21 | construct,
22 | func,
23 | object,
24 | value_reference,
25 | number_value,
26 | string_value,
27 | property){
28 | "use strict";
29 |
30 | /* Operations
31 | ******************************************************************************/
32 | /**
33 | * Create a new hosted language function.
34 | */
35 | var create = function(scope, strict, id, names, code, declarations, body) {
36 | return compute.binary(
37 | value_reference.create(
38 | meta_language_function.LanguageFunction.create(
39 | func_builtin.FunctionPrototype,
40 | {},
41 | true,
42 | scope,
43 | strict,
44 | id,
45 | names,
46 | code,
47 | declarations,
48 | body)),
49 | object_builtin.create(),
50 | function(impl, proto) {
51 | return object.defineProperties(impl, {
52 | 'prototype': property.createValuePropertyFlags(
53 | proto,
54 | property.WRITABLE | property.CONFIGURABLE),
55 |
56 | 'length': property.createValuePropertyFlags(
57 | new number_value.Number(length)),
58 |
59 | 'name': property.createValuePropertyFlags(
60 | (id ? new string_value.String(id) : string_value.EMPTY))
61 | });
62 | });
63 | };
64 |
65 | /* Export
66 | ******************************************************************************/
67 | exports.create = create;
68 |
69 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number builtin operations
3 | */
4 | define(['exports',
5 | 'atum/builtin/number',
6 | 'atum/operations/construct'],
7 | function(exports,
8 | builtin_number,
9 | construct){
10 | "use strict";
11 |
12 | /* Operations
13 | ******************************************************************************/
14 | /**
15 | * Create a new builtin number object
16 | *
17 | * @param primitiveValue Value stored in number object.
18 | */
19 | var create = function(primitiveValue) {
20 | return construct.construct(builtin_number.Number, [primitiveValue]);
21 | };
22 |
23 | /* Export
24 | ******************************************************************************/
25 | exports.create = create;
26 |
27 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Object builtin operations
3 | */
4 | define(['exports',
5 | 'atum/builtin/object',
6 | 'atum/operations/construct'],
7 | function(exports,
8 | builtin_object,
9 | construct){
10 | "use strict";
11 |
12 | /* Operations
13 | ******************************************************************************/
14 | /**
15 | * Create a new builtin object.
16 | */
17 | var create = function() {
18 | return construct.construct(builtin_object.Object, []);
19 | };
20 |
21 | /* Export
22 | ******************************************************************************/
23 | exports.create = create;
24 |
25 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Regular expression builtin operations
3 | */
4 | define(['exports',
5 | 'atum/builtin/regexp',
6 | 'atum/operations/construct',
7 | 'atum/value/string'],
8 | function(exports,
9 | regexp_builtin,
10 | construct,
11 | string){
12 | "use strict";
13 |
14 | /* Operations
15 | ******************************************************************************/
16 | /**
17 | * Create a new regular expression object
18 | *
19 | * @param body Hosted string for body of regular expression.
20 | * @param flags Hosted string for flags on expression
21 | */
22 | var create = function(body, flags) {
23 | return construct.construct(
24 | regexp_builtin.RegExp,
25 | [body, flags]);
26 | };
27 |
28 | var createFromHost = function(body, flags) {
29 | return create(
30 | new string.String(body),
31 | new string.String(flags));
32 | };
33 |
34 | /* Export
35 | ******************************************************************************/
36 | exports.create = create;
37 | exports.createFromHost = createFromHost;
38 |
39 | });
--------------------------------------------------------------------------------
/lib/builtin/operations/string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview String builtin operations
3 | */
4 | define(['exports',
5 | 'atum/builtin/string',
6 | 'atum/operations/construct'],
7 | function(exports,
8 | builtin_string,
9 | construct){
10 | "use strict";
11 |
12 | /* Operations
13 | ******************************************************************************/
14 | /**
15 | * Create a new builtin string object
16 | *
17 | * @param primitiveValue Value stored in string object.
18 | */
19 | var create = function(primitiveValue) {
20 | return construct.construct(builtin_string.String, [primitiveValue]);
21 | };
22 |
23 | /* Export
24 | ******************************************************************************/
25 | exports.create = create;
26 |
27 | });
--------------------------------------------------------------------------------
/lib/builtin/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin RegExp Object References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'RegExp': vr.create('RegExp'),
12 |
13 | 'RegExpPrototype': vr.create('RegExp.prototype'),
14 | 'RegExpPrototypeExec': vr.create('RegExp.prototype.exec'),
15 | 'RegExpPrototypeToString': vr.create('RegExp.prototype.toString')
16 | };
17 |
18 | });
--------------------------------------------------------------------------------
/lib/builtin/string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Exported Builtin String Object References
3 | */
4 | define(['atum/value_reference'],
5 | function(vr){
6 | "use strict";
7 |
8 | /* Exports
9 | ******************************************************************************/
10 | return {
11 | 'String': vr.create('String'),
12 |
13 | 'StringPrototype': vr.create('String.prototype'),
14 | 'StringPrototypeCharCodeAt': vr.create('String.prototype.charCodeAt'),
15 | 'StringPrototypeMatch': vr.create('String.prototype.match'),
16 | 'StringPrototypeReplace': vr.create('String.prototype.replace'),
17 | 'StringPrototypeSplit': vr.create('String.prototype.split'),
18 | 'StringPrototypeToString': vr.create('String.prototype.toString'),
19 | 'StringPrototypeValueOf': vr.create('String.prototype.valueOf')
20 | };
21 |
22 | });
--------------------------------------------------------------------------------
/lib/compute/cont.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Delimited continuation control stack.
3 | *
4 | * Based on:
5 | * http://www.cs.indiana.edu/~sabry/papers/monadicDC.pdf
6 | */
7 | define(['nu-stream/stream'],
8 | function(stream) {
9 | "use strict";
10 |
11 | /* Records
12 | ******************************************************************************/
13 | /**
14 | * Control segment.
15 | */
16 | var Seg = function(f) {
17 | this.frame = f;
18 | };
19 |
20 | /**
21 | * Delimiter.
22 | */
23 | var P = function(t) {
24 | this.prompt = t;
25 | };
26 |
27 | /* Control Stack
28 | ******************************************************************************/
29 | var empty = stream.NIL;
30 |
31 | var push = stream.cons;
32 |
33 | /**
34 | * Push an entire slice of control stack onto a control stack.
35 | */
36 | var pushSeq = stream.append;
37 |
38 | /**
39 | * Push a delimiter `t` on onto control stack `k`.
40 | */
41 | var pushP = function(t, k) {
42 | return push(new P(t), k);
43 | };
44 |
45 | /**
46 | * Push a segment for `f` onto control stack `k`.
47 | */
48 | var pushSeg = function(f, k) {
49 | return push(new Seg(f), k);
50 | };
51 |
52 | /**
53 | * Splits the control stack around prompt `t`.
54 | */
55 | var splitSeq = function(t, k) {
56 | if (stream.isEmpty(k) )
57 | return [k, empty];
58 |
59 | // TODO: Supra the hacks
60 | if (typeof k === 'function')
61 | return [push(k, empty), empty];
62 |
63 | var top = stream.first(k),
64 | rest = stream.rest(k);
65 |
66 | if (top instanceof P && top.prompt === t)
67 | return [empty, rest];
68 |
69 | var sub = splitSeq(t, rest);
70 | return [push(top, sub[0]), sub[1]];
71 | };
72 |
73 | /* Operations
74 | ******************************************************************************/
75 | /**
76 | * Apply continuation `k`
77 | *
78 | * @param k Continuation.
79 | * @param x Value
80 | * @param ctx State.
81 | */
82 | var appk = function(k, x, ctx) {
83 | do {
84 | if (typeof k === 'function')
85 | return k(x, ctx);
86 |
87 | var top = stream.first(k);
88 | if (top instanceof Seg)
89 | return top.frame(x)(ctx, stream.rest(k));
90 | else if (top instanceof P)
91 | k = stream.rest(k);
92 | else
93 | k = top;
94 | } while (true);
95 | };
96 |
97 | /* Export
98 | ******************************************************************************/
99 | return {
100 | 'push': push,
101 | 'pushP': pushP,
102 | 'pushSeg': pushSeg,
103 | 'pushSeq': pushSeq,
104 | 'splitSeq': splitSeq,
105 |
106 | 'empty': empty,
107 |
108 | // Operations
109 | 'appk': appk
110 | };
111 |
112 | });
--------------------------------------------------------------------------------
/lib/compute/context.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Computation state record.
3 | */
4 | define(['bes/record',
5 | 'hamt'],
6 | function(record,
7 | hamt) {
8 | "use strict";
9 |
10 | /* Context
11 | ******************************************************************************/
12 | /**
13 | * Computation state.
14 | *
15 | * @param values Object that maps keys to values referenced in a computation.
16 | * @param userData User computation context.
17 | * @param unique Open unique identifier.
18 | * @param fail Prompt of enclosing failure computation.
19 | */
20 | var ComputeContext = record.declare(null, [
21 | 'values',
22 | 'userData',
23 | 'unique',
24 | 'fail']);
25 |
26 | /**
27 | * Empty computation context that stores no values and has no user data.
28 | */
29 | ComputeContext.empty = ComputeContext.create(hamt.empty, null, 1, 0);
30 |
31 | /* Export
32 | ******************************************************************************/
33 | return {
34 | 'ComputeContext': ComputeContext
35 | };
36 |
37 | });
--------------------------------------------------------------------------------
/lib/compute/io.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Base statement computations.
3 | */
4 | define(['atum/compute',
5 | 'atum/completion',
6 | 'atum/fun',
7 | 'atum/compute/cont',
8 | 'atum/compute/tail'],
9 | function(compute,
10 | completion,
11 | fun,
12 | cont,
13 | tail) {
14 | "use strict";
15 |
16 | /* Base
17 | ******************************************************************************/
18 | var fmap = function(f, action) {
19 | return function() {
20 | return f(action());
21 | };
22 | };
23 |
24 | var join = function(action) {
25 | return function() {
26 | return action()();
27 | };
28 | };
29 |
30 | var just = function(x) {
31 | return function() {
32 | return x;
33 | };
34 | };
35 |
36 | var bind = function(action, f) {
37 | return join(fmap(f, action));
38 | };
39 |
40 | var next = function(p, q) {
41 | return bind(p, fun.constant(q));
42 | };
43 |
44 | /* Try
45 | ******************************************************************************/
46 | var handle = function(action, ok, err) {
47 | return bind(
48 | function() {
49 | try {
50 | var x = action();
51 | return [true, x];
52 | } catch (e) {
53 | return [false, e];
54 | }
55 | },
56 | function(result) {
57 | return (result[0] ?
58 | ok(result[1]) :
59 | err(result[1]))
60 | });
61 | };
62 |
63 | /*
64 | ******************************************************************************/
65 | var now = Date.now;
66 |
67 | var random = Math.random;
68 |
69 | var getFile = function(path) {
70 | return function() {
71 | if (typeof module !== 'undefined' && module.exports) {
72 | var fs = require.nodeRequire('fs');
73 | return fs.readFileSync(path, 'utf8');
74 | }
75 |
76 | var xhr = new XMLHttpRequest();
77 | xhr.open('GET', path, false);
78 | xhr.send(null);
79 |
80 | if (xhr.status > 399 && xhr.status < 600)
81 | throw new Error(path + ' HTTP status: ' + xhr.status);
82 |
83 | return xhr.responseText;
84 | };
85 | }
86 |
87 | /* Running
88 | ******************************************************************************/
89 | var perform = function(action) {
90 | return action()
91 | };
92 |
93 | /* Export
94 | ******************************************************************************/
95 | return {
96 | 'just': just,
97 | 'bind': bind,
98 |
99 | 'handle': handle,
100 |
101 | 'now': now,
102 | 'random': random,
103 | 'getFile': getFile,
104 |
105 | 'perform': perform
106 | };
107 |
108 | });
--------------------------------------------------------------------------------
/lib/compute/program.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Program computation operations.
3 | *
4 | * Interfaces for wrapping statement computations and running program computations
5 | * with a error callback
6 | */
7 | define(['atum/completion',
8 | 'atum/compute',
9 | 'atum/compute/cont',
10 | 'atum/compute/tail'],
11 | function(completion,
12 | compute,
13 | cont,
14 | tail) {
15 | "use strict";
16 |
17 | /* Running
18 | ******************************************************************************/
19 | /**
20 | * Run a computation with an explicit error callback.
21 | *
22 | * Error callback has the same interface as the success callback.
23 | *
24 | * @param c Computation.
25 | * @param ctx Computation context.
26 | * @param ok Success callback.
27 | * @param err Failure callback.
28 | */
29 | var run = function(c, ctx, ok, err) {
30 | var prog = compute.bindError(c, function(x) {
31 | return compute.bind(compute.computeContext, function(ctx) {
32 | return compute.abrupt(err(x, ctx));
33 | });
34 | });
35 | return tail.trampoline(
36 | prog(ctx, cont.push(ok, cont.empty)));
37 | };
38 |
39 | /* Base Computations
40 | ******************************************************************************/
41 | /**
42 | * Evaluate a statement computation and pass results to a function which
43 | * returns a program computation.
44 | */
45 | var bindStatement = function(statement, f) {
46 | return function(ctx, k) {
47 | //var r = statement(ctx);
48 | //return f(r[0])(r[1], k);
49 |
50 | return statement(ctx,
51 | function(x, ctx) {
52 | return f(x)(ctx, k);
53 | });
54 | };
55 | };
56 |
57 | /**
58 | * Transform a statement computation into a program computation.
59 | */
60 | var liftStatement = function(statement) {
61 | return bindStatement(statement, function(x) {
62 | switch (x.type) {
63 | case completion.ThrowCompletion.type:
64 | return compute.error(x.value);
65 |
66 | case completion.NormalCompletion.type:
67 | return compute.just(x.value);
68 | }
69 | return compute.abrupt(x);
70 | });
71 | };
72 |
73 |
74 | /* Export
75 | ******************************************************************************/
76 | return {
77 | // Running
78 | 'run': run,
79 |
80 | // Statement Interface
81 | 'liftStatement': liftStatement,
82 | 'bindStatement': bindStatement
83 | };
84 |
85 | });
--------------------------------------------------------------------------------
/lib/compute/tail.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Tail calls
3 | */
4 | define([],
5 | function() {
6 | "use strict";
7 |
8 | /**
9 | * Tail call.
10 | *
11 | * @param f Function to call.
12 | */
13 | var Tail = function(f, ctx, k) {
14 | this.f = f;
15 | this.ctx = ctx;
16 | this.k = k;
17 | };
18 |
19 | /**
20 | * Repeatedly evaluate tail calls until a value is found.
21 | */
22 | var trampoline = function(f) {
23 | var value = f;
24 | while (value instanceof Tail)
25 | value = value.f(value.ctx, value.k);
26 | return value;
27 | };
28 |
29 | /* Export
30 | ******************************************************************************/
31 | return {
32 | 'Tail': Tail,
33 | 'trampoline': trampoline
34 | };
35 |
36 | });
--------------------------------------------------------------------------------
/lib/context/environment_record.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Data structures and operations for creating and manipulating
3 | * environment records.
4 | */
5 | define(['hamt',
6 | 'bes/record'],
7 | function(hamt,
8 | record) {
9 | "use strict";
10 |
11 | /* Binding
12 | ******************************************************************************/
13 | /**
14 | * Environment binding.
15 | *
16 | * @param value Value bound.
17 | * @param mutable Is the binding mutable?
18 | */
19 | var Binding = record.declare(null,[
20 | 'value',
21 | 'mutable']);
22 |
23 | /* Environment Record
24 | ******************************************************************************/
25 | /**
26 | * Get the binding for `name` in `record`.
27 | */
28 | var getBinding = hamt.get;
29 |
30 | /**
31 | * Does the given environment record have a binding for `name`.
32 | *
33 | * @param env Environment record.
34 | * @param {string} name Binding name to check.
35 | */
36 | var hasBinding = hamt.has;
37 |
38 | /**
39 | * Does the given environment record have a mutable binding for `name`.
40 | *
41 | * @param env Environment record.
42 | * @param {string} name Binding name to check.
43 | */
44 | var hasMutableBinding = function(record, name) {
45 | return (hasBinding(record, name) && getBinding(name, record).mutable);
46 | };
47 |
48 | /**
49 | * Get the value bound for `name` in `record`.
50 | */
51 | var getBindingValue = function(record, name) {
52 | return getBinding(name, record).value;
53 | };
54 |
55 | /**
56 | * Create a new environment record from 'record' with mutable binding for 'n' to 'v'.
57 | *
58 | * @param record Environment record.
59 | * @param {string} name Binding name
60 | * @param v Binding value.
61 | */
62 | var setMutableBinding = function(record, name, v) {
63 | return hamt.set(
64 | name,
65 | Binding.create(v, true),
66 | record);
67 | };
68 |
69 | /**
70 | * Create a new environment record from 'record' with immutable binding for 'n' to 'v'.
71 | *
72 | * @param record Environment record.
73 | * @param {string} name Binding name
74 | * @param v Binding value.
75 | */
76 | var putImmutableBinding = function(record, name, v) {
77 | return hamt.set(
78 | name,
79 | Binding.create(v, false),
80 | record);
81 | };
82 |
83 | /**
84 | * Create a new environment record from `record` with the binding for `name`
85 | * removed.
86 | *
87 | * @param {string} name Binding name.
88 | * @param record Environment record.
89 | */
90 | var deleteBinding = hamt.remove;
91 |
92 | /* Export
93 | ******************************************************************************/
94 | return {
95 | 'empty': hamt.empty,
96 |
97 | 'hasBinding': hasBinding,
98 | 'hasMutableBinding': hasMutableBinding,
99 |
100 | 'getBindingValue': getBindingValue,
101 | 'setMutableBinding': setMutableBinding,
102 | 'putImmutableBinding': putImmutableBinding,
103 | 'deleteBinding': deleteBinding
104 | };
105 |
106 | });
--------------------------------------------------------------------------------
/lib/context/environment_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview EnvironmentReference reference type.
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/compute',
7 | 'atum/internal_reference',
8 | 'atum/operations/environment',
9 | 'atum/operations/error',
10 | 'atum/operations/execution_context',
11 | 'atum/operations/internal_reference',
12 | 'atum/operations/undef'],
13 | function(exports,
14 | record,
15 | compute,
16 | internal_reference,
17 | environment,
18 | error,
19 | execution_context,
20 | internal_reference_operations,
21 | undef) {
22 | "use strict";
23 |
24 | /* Environment Reference
25 | ******************************************************************************/
26 | /**
27 | * Reference to a value in an environment.
28 | *
29 | * @param {String} name Identifier used to lookup referenced value.
30 | * @param [base] Reference to the object storing the referenced value. If null,
31 | * assumed to be the global object.
32 | * @param {Boolean} [strict] Is the reference strict.
33 | */
34 | var EnvironmentReference = record.declare(new internal_reference.InternalReference, [
35 | 'name',
36 | 'base',
37 | 'strict'],
38 | function(name, base, strict) {
39 | this.name = name + '';
40 | this.base = base;
41 | this.strict = !!strict;
42 |
43 | this.isUnresolvable = !base;
44 |
45 | this.getBase = (this.isUnresolvable ?
46 | error.referenceError(this.name) :
47 | internal_reference_operations.getValue(this.base));
48 |
49 | this.thisValue = compute.bind(this.getBase, function(base) {
50 | return base.implicitThisValue;
51 | });
52 | });
53 |
54 | /**
55 | * Computation that dereferences the stored value.
56 | *
57 | * Errors if the value cannot be dereferenced.
58 | */
59 | EnvironmentReference.prototype.getValue = function() {
60 | var name = this.name,
61 | strict = this.strict;
62 | return compute.bind(this.getBase, function(env) {
63 | return compute.branch(env.hasOwnBinding(name, strict),
64 | env.getBindingValue(name, strict),
65 | undef.UNDEFINED);
66 | });
67 | };
68 |
69 | /**
70 | * Set value stored in this reference.
71 | *
72 | * @param value New value to store.
73 | */
74 | EnvironmentReference.prototype.setValue = function(value) {
75 | if (this.isUnresolvable && this.strict)
76 | return error.referenceError(this.name);
77 |
78 | var name = this.name,
79 | strict = this.strict;
80 |
81 | return compute.next(
82 | compute.bind(
83 | (this.isUnresolvable ? environment.global : compute.just(this.base)),
84 | function(env) {
85 | return environment.setEnvironmentMutableBinding(
86 | env,
87 | strict,
88 | name,
89 | value);
90 | }),
91 | compute.just(this));
92 | };
93 |
94 | /**
95 | * Delete the value stored for this reference.
96 | *
97 | * Errors if called in strict mode.
98 | *
99 | * Returns whether the operations was successful.
100 | */
101 | EnvironmentReference.prototype.deleteReference = function() {
102 | if (this.strict)
103 | return error.syntaxError();
104 |
105 | if (this.isUnresolvable)
106 | return compute.yes;
107 |
108 | return environment.deleteEnvironmentBinding(this.base, this.name);
109 | };
110 |
111 | /* Operations
112 | ******************************************************************************/
113 | /**
114 | * Create a new environment reference.
115 | */
116 | var createStrictness = compute.from(EnvironmentReference.create);
117 |
118 | /**
119 | * Create a new environment reference.
120 | *
121 | * Gets the strictness from the current environment.
122 | */
123 | var create = function(name, base) {
124 | return compute.bind(
125 | execution_context.strict,
126 | function(strict) {
127 | return createStrictness(name, base, strict);
128 | });
129 | };
130 |
131 | /* Export
132 | ******************************************************************************/
133 | exports.EnvironmentReference = EnvironmentReference;
134 |
135 | exports.createStrictness = createStrictness;
136 | exports.create = create;
137 |
138 | });
--------------------------------------------------------------------------------
/lib/context/execution_context.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview ECMAscript execution context.
3 | */
4 | define(['bes/record',
5 | 'atum/context/execution_metadata'],
6 | function(record,
7 | execution_metadata) {
8 | "use strict";
9 |
10 | /* Execution Context
11 | ******************************************************************************/
12 | /**
13 | * ECMAScript execution context.
14 | *
15 | * @member settings Execution settings.
16 | * @member strict Is the context in strict mode?
17 | * @member lexicalEnvironment Lexical environment of program.
18 | * @member variableEnvironment Declarative environment of program.
19 | * @member global Reference to global object.
20 | * @member metadata Execution metadata.
21 | * @member semantics
22 | */
23 | var ExecutionContext = record.declare(null, [
24 | 'settings',
25 | 'strict',
26 | 'lexicalEnvironment',
27 | 'variableEnvironment',
28 | 'thisBinding',
29 | 'global',
30 | 'metadata',
31 | 'semantics']);
32 |
33 | ExecutionContext.empty = ExecutionContext.create(
34 | null,
35 | false,
36 | null,
37 | null,
38 | null,
39 | null,
40 | execution_metadata.empty,
41 | null);
42 |
43 | /* Creation
44 | ******************************************************************************/
45 | /**
46 | * Create a new, global execution context.
47 | *
48 | * @param settings Execution settings.
49 | * @param env Reference to global environment.
50 | * @param obj Reference to global object.
51 | * @param semantics
52 | */
53 | var createGlobalContext = function(settings, env, obj, semantics) {
54 | return ExecutionContext.create(
55 | settings,
56 | false,
57 | env,
58 | env,
59 | obj,
60 | env,
61 | execution_metadata.empty,
62 | semantics);
63 | };
64 |
65 | /* Export
66 | ******************************************************************************/
67 | return {
68 | 'ExecutionContext': ExecutionContext,
69 |
70 | // Creation
71 | 'createGlobalContext': createGlobalContext
72 | };
73 |
74 | });
--------------------------------------------------------------------------------
/lib/context/execution_metadata.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Execution context metadata.
3 | */
4 | define(['bes/record'],
5 | function(record) {
6 | "use strict";
7 |
8 | /* ExecutionMetadata
9 | ******************************************************************************/
10 | /**
11 | * Execution context metadata.
12 | *
13 | * Stores data that is not directly used for execution but may be useful for
14 | * tooling.
15 | *
16 | * @member stack Array of stack frames for the complete stack.
17 | * @member loc Program kocation of execution.
18 | * @member errorHandlers Array of error handlers for complete error handler stack.
19 | */
20 | var ExecutionMetadata = record.declare(null, [
21 | 'stack',
22 | 'loc',
23 | 'errorHandlers']);
24 |
25 | /**
26 | * Empty execution context metadata
27 | */
28 | var empty = new ExecutionMetadata([], null, []);
29 |
30 | /* Export
31 | ******************************************************************************/
32 | return {
33 | 'ExecutionMetadata': ExecutionMetadata,
34 |
35 | 'empty': empty
36 | };
37 |
38 | });
--------------------------------------------------------------------------------
/lib/context/execution_settings.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Execution settings.
3 | */
4 | define(['bes/record'],
5 | function(record) {
6 | "use strict";
7 |
8 | /* ExecutionSettings
9 | ******************************************************************************/
10 | /**
11 | * Settings for program execution.
12 | */
13 | var ExecutionSettings = record.declare(null, [
14 | 'maxStack']);
15 |
16 | /* Defaults
17 | ******************************************************************************/
18 | /**
19 | * Default maximum size of call stack.
20 | */
21 | var MAX_STACK = 1000;
22 |
23 | /**
24 | * Default settings.
25 | */
26 | var DEFAULTS = new ExecutionSettings(
27 | MAX_STACK);
28 |
29 | /* Export
30 | ******************************************************************************/
31 | return {
32 | 'ExecutionSettings': ExecutionSettings,
33 |
34 | // Defaults
35 | 'MAX_STACK': MAX_STACK,
36 |
37 | 'DEFAULTS': DEFAULTS
38 | };
39 |
40 | });
--------------------------------------------------------------------------------
/lib/context/property_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview PropertyReference reference type.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/internal_reference',
7 | 'atum/operations/boolean',
8 | 'atum/operations/error',
9 | 'atum/operations/execution_context',
10 | 'atum/operations/internal_reference',
11 | 'atum/operations/object',
12 | 'atum/operations/type_conversion',
13 | 'atum/value/property',
14 | 'atum/value/value'],
15 | function(exports,
16 | compute,
17 | internal_reference,
18 | boolean,
19 | error,
20 | execution_context,
21 | internal_reference_operations,
22 | object,
23 | type_conversion,
24 | property,
25 | value) {
26 | "use strict";
27 |
28 | /**
29 | * object.set for strict mode.
30 | */
31 | var strictSetter = function(o, name, value) {
32 | return compute.bind(object.getProperty(o, name), function(prop) {
33 | if (prop) {
34 | if ((property.isDataDescriptor(prop) && !prop.writable))
35 | return error.typeError('Value for "' + name + '" is not writable');
36 | else if ((property.isAccessorDescriptor(prop) && !prop.set))
37 | return error.typeError('Accessor for "' + name + '" has no setter');
38 | } else {
39 | return compute.branch(object.isExtensible(o),
40 | object.set(o, name, value),
41 | error.typeError());
42 | }
43 | return object.set(o, nam, value);
44 | });
45 | };
46 |
47 | /* Property Reference
48 | ******************************************************************************/
49 | /**
50 | * Language level reference to a property stored in a base object.
51 | */
52 | var PropertyReference = function(name, base, strict) {
53 | this.name = name + '';
54 | this.base = base;
55 | this.strict = !!strict;
56 |
57 | this.isUnresolvable = !base;
58 | this.hasPrimitiveBase = (!this.isUnresolvable && (value.isBoolean(base) || value.isString(base) || value.isNumber(base)));
59 | this.isProperty = (!this.isUnresolvable && (value.isObject(base) || this.hasPrimitiveBase));
60 |
61 | this.getBase = (this.isUnresolvable ?
62 | error.referenceError(this.name) :
63 | internal_reference_operations.dereference(this.base, type_conversion.toObject));
64 |
65 | this.thisValue = this.getBase;
66 | };
67 | PropertyReference.prototype = new internal_reference.InternalReference;
68 |
69 | /**
70 | * Get the value stored for this reference.
71 | */
72 | PropertyReference.prototype.getValue = function() {
73 | var name = this.name;
74 | return compute.bind(this.getBase, function(o){
75 | return object.get(o, name);
76 | });
77 | };
78 |
79 | /**
80 | * Set the value stored for this reference.
81 | */
82 | PropertyReference.prototype.setValue = function(value) {
83 | var name = this.name, strict = this.strict;
84 | return compute.next(
85 | compute.bind(this.getBase, function(o) {
86 | return (strict ? strictSetter : object.set)(o, name, value);
87 | }),
88 | compute.just(this));
89 | };
90 |
91 | /**
92 | * Delete the value stored for this reference.
93 | */
94 | PropertyReference.prototype.deleteReference = function() {
95 | if (this.isUnresolvable) {
96 | if (this.strict)
97 | return error.syntaxError();
98 | return compute.yes;
99 | }
100 | var name = this.name,
101 | strict = this.strict;
102 | return compute.bind(this.getBase, function(base) {
103 | return object.deleteStrictnessProperty(base, strict, name);
104 | });
105 | };
106 |
107 | /* Operations
108 | ******************************************************************************/
109 | /**
110 | * Create a new property reference.
111 | *
112 | * Gets the strictness from the current environment.
113 | */
114 | var create = function(name, base) {
115 | return compute.map(
116 | execution_context.strict,
117 | function(strict) {
118 | return new PropertyReference(name, base, strict);
119 | });
120 | };
121 |
122 | /* Exports
123 | ******************************************************************************/
124 | exports.PropertyReference = PropertyReference;
125 |
126 | exports.create = create;
127 |
128 | });
--------------------------------------------------------------------------------
/lib/context/stack_frame.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Stack metadata
3 | */
4 | define(['bes/record'],
5 | function(record) {
6 | "use strict";
7 |
8 | /* StackFrame
9 | ******************************************************************************/
10 | /**
11 | * Stack frame metadata object.
12 | *
13 | * @member prompt Control stack delimiter of call.
14 | * @member func The function for the current frame.
15 | * @member environment The frame's environment.
16 | * @member location Execution location in the stack frame.
17 | */
18 | var StackFrame = record.declare(null, [
19 | 'prompt',
20 | 'callee',
21 | 'args',
22 | 'environment',
23 | 'location']);
24 |
25 | /* Export
26 | ******************************************************************************/
27 | return {
28 | 'StackFrame': StackFrame
29 | };
30 |
31 | });
--------------------------------------------------------------------------------
/lib/external/importScripts.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview `importScripts` hosted function.
3 | */
4 | define(['atum/compute',
5 | 'atum/value_reference',
6 | 'atum/operations/evaluation',
7 | 'atum/operations/string'],
8 | function(compute,
9 | value_reference,
10 | evaluation,
11 | string){
12 | "use strict";
13 |
14 | /* `importScripts`
15 | ******************************************************************************/
16 | var ref = value_reference.create('importScripts');
17 |
18 | var importScripts = function(ref, thisObj, args) {
19 | if (args.length === 0)
20 | return error.typeError();
21 |
22 | return compute.bind(
23 | string.toHost(args.getArg(0)),
24 | evaluation.evaluateUrlFile);
25 | };
26 |
27 | /* initialization
28 | ******************************************************************************/
29 | var initialize = function(mutableBinding, immutableBinding) {
30 | var func_builtin = require('atum/builtin/operations/builtin_function');
31 | return func_builtin.create(ref, 'importScripts', 1, importScripts);
32 | };
33 |
34 | var configure = function(mutableBinding, immutableBinding) {
35 | return mutableBinding('importScripts', ref);
36 | };
37 |
38 | var execute = function() {
39 | return compute.empty;
40 | };
41 |
42 | /* Exports
43 | ******************************************************************************/
44 | return {
45 | 'importScripts': ref,
46 | 'initialize': initialize,
47 | 'configure': configure,
48 | 'execute': execute
49 | };
50 |
51 | });
--------------------------------------------------------------------------------
/lib/fun.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | define([],
5 | function(){
6 | "use strict";
7 |
8 | /*
9 | ******************************************************************************/
10 | /**
11 | * Identify function
12 | */
13 | var identity = function(x) {
14 | return x;
15 | };
16 |
17 | /**
18 | * Return the function arguments.
19 | */
20 | var args = function(/*...*/) {
21 | return arguments;
22 | };
23 |
24 | /**
25 | * Create a constant function that returns `x`.
26 | */
27 | var constant = function(x) {
28 | return function() {
29 | return x;
30 | };
31 | };
32 |
33 | /**
34 | * Create a flipped argument version of binary function `f`.
35 | */
36 | var flip = function(f) {
37 | return function(x, y) {
38 | return f(y, x);
39 | };
40 | };
41 |
42 | /**
43 | * Compose two unary argument functions `f` and `g`.
44 | */
45 | var compose = function(f, g) {
46 | if (!f || !g) debugger;
47 | return function(x) {
48 | return f(g(x));
49 | };
50 | };
51 |
52 | /**
53 | * Compose n-ary function `g` with unary argument function `f`.
54 | */
55 | var composen = function(f, g) {
56 | if (!f || !g) debugger;
57 | return function(/*...*/) {
58 | return f(g.apply(undefined, arguments));
59 | };
60 | };
61 |
62 | /*
63 | ******************************************************************************/
64 | var concat = Array.prototype.concat.bind([]);
65 |
66 | var slice = function(start, end, a) {
67 | return Array.prototype.slice.call(a, start, end);
68 | };
69 |
70 | var map = function(f, a) {
71 | return Array.prototype.map.call(a, f);
72 | };
73 |
74 | var foldl = function(f, z, a) {
75 | return Array.prototype.reduce.call(a, f, z);
76 | };
77 |
78 | var foldr = function(f, z, a) {
79 | return Array.prototype.reduceRight.call(a, f, z);
80 | };
81 |
82 | var reduce = function(f, a) {
83 | return Array.prototype.reduce.call(a, f);
84 | };
85 |
86 | var reduceRight = function(f, a) {
87 | return Array.prototype.reduceRight.call(a, f);
88 | };
89 |
90 | /*
91 | ******************************************************************************/
92 | var _ = {};
93 |
94 | var curry = function(f /*, ...*/) {
95 | return f.bind.apply(f, arguments);
96 | };
97 |
98 | var placeholder = function(f /*, ...*/) {
99 | var bound = slice(1, undefined, arguments);
100 | return function(/*...*/) {
101 | var args = [];
102 | for (var i = 0, len = bound.length; i < len; ++i)
103 | if (bound[i] !== _)
104 | args[i] = bound[i];
105 | var indx = 0;
106 | for (var i = 0, len = arguments.length; i < len; ++i) {
107 | while (indx in args)
108 | ++indx;
109 | args[indx++] = arguments[i];
110 | }
111 | return f.apply(undefined, args);
112 | };
113 | };
114 |
115 | /*
116 | ******************************************************************************/
117 | var range = (function(){
118 | var rangeImpl = function(lower, upper, step) {
119 | var arr = [];
120 | while (step > 0 ? upper > lower : upper < lower) {
121 | arr.push(lower);
122 | lower += step;
123 | }
124 | return arr;
125 | };
126 | return function(lower, upper, step) {
127 | var rangeLower = isNaN(lower) ? Infinity : +lower;
128 | var rangeStep = isNaN(step) ? 1 : +step;
129 | return isNaN(upper) ?
130 | rangeImpl(0, rangeLower, rangeStep) :
131 | rangeImpl(rangeLower, upper, rangeStep);
132 | };
133 | }());
134 |
135 | var gen = function(end) {
136 | return range(0, end, 1);
137 | };
138 |
139 | /* Export
140 | ******************************************************************************/
141 | return {
142 | 'identity': identity,
143 | 'args': args,
144 | 'constant': constant,
145 |
146 | 'compose': compose,
147 | 'composen': composen,
148 |
149 | 'flip': flip,
150 |
151 | '_': _,
152 | 'curry': curry,
153 | 'placeholder': placeholder,
154 |
155 | 'concat': concat,
156 | 'map': map,
157 | 'foldl': foldl,
158 | 'foldr': foldr,
159 | 'reduce': reduce,
160 | 'reduceRight': reduceRight,
161 | 'slice': slice,
162 |
163 | 'gen': gen,
164 | 'range': range
165 | };
166 |
167 | });
--------------------------------------------------------------------------------
/lib/internal_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Interface for references used internally.
3 | */
4 | define(['atum/reference'],
5 | function(reference){
6 | "use strict";
7 |
8 | /* InternalReference
9 | ******************************************************************************/
10 | /**
11 | * Interface / marker class for references used in the interpreter implementation.
12 | */
13 | var InternalReference = function() { };
14 |
15 | InternalReference.prototype = new reference.Reference;
16 |
17 | /* Export
18 | ******************************************************************************/
19 | return {
20 | 'InternalReference': InternalReference
21 | };
22 |
23 | });
--------------------------------------------------------------------------------
/lib/interpret.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Functions for interpreting an ECMAScript abstract syntax tree.
3 | */
4 | define(['exports',
5 | 'atum/compute/context',
6 | 'atum/compute/program',
7 | 'atum/operations/evaluation'],
8 | function(exports,
9 | context,
10 | program,
11 | evaluation){
12 | "use strict";
13 |
14 | /* Callbacks
15 | ******************************************************************************/
16 | /**
17 | * Standard success callback.
18 | *
19 | * Returns 'x'.
20 | */
21 | var ret = function(x, ctx) {
22 | return x;
23 | };
24 |
25 | /**
26 | * Standard error callback.
27 | *
28 | * Throws 'x'.
29 | */
30 | var thr = function(x, ctx) {
31 | throw x;
32 | };
33 |
34 | /**
35 | * Noop
36 | */
37 | var noop = function() { };
38 |
39 | /* Interpretation
40 | ******************************************************************************/
41 | /**
42 | * Execute `p` with given context and callbacks.
43 | */
44 | var exec = function(p, ctx, ok, err) {
45 | return program.run(p, ctx, ok, err);
46 | };
47 |
48 | /**
49 | * Perform `p` in `ctx` with standard callbacks.
50 | */
51 | var runContext = function(p, ctx) {
52 | return exec(p, ctx, ret, thr);
53 | };
54 |
55 | /**
56 | * Perform `p` with standard callbacks.
57 | */
58 | var run = function(p) {
59 | return runContext(p, context.ComputeContext.empty);
60 | };
61 |
62 | /**
63 | * Interpret AST `root` to completion with given context and callbacks.
64 | */
65 | var interpret = function(root, ctx, ok, err) {
66 | return exec(evaluation.evaluateAst(root), ctx, ok, err);
67 | };
68 |
69 | /**
70 | * Interprets AST `root` to completion with standard callbacks.
71 | */
72 | var evaluateContext = function(root, ctx) {
73 | return interpret(root, ctx, ret, thr);
74 | };
75 |
76 | /**
77 | * Interprets AST `root` to completion with empty context and callbacks.
78 | *
79 | */
80 | var evaluate = function(root) {
81 | return evaluateContext(root, context.ComputeContext.empty);
82 | };
83 |
84 | /* Export
85 | ******************************************************************************/
86 | // Callbacks
87 | exports.ret = ret;
88 | exports.thr = thr;
89 | exports.noop = noop;
90 |
91 | // Evaluation
92 | exports.exec = exec;
93 |
94 | exports.runContext = runContext;
95 | exports.run = run;
96 |
97 | exports.interpret = interpret;
98 |
99 | exports.evaluateContext = evaluateContext;
100 | exports.evaluate = evaluate;
101 |
102 | });
--------------------------------------------------------------------------------
/lib/iref.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | define(['bes/record',
5 | 'atum/compute',
6 | 'atum/internal_reference'],
7 | function(record,
8 | compute,
9 | internal_reference) {
10 | "use strict";
11 |
12 | /* Iref
13 | ******************************************************************************/
14 | /**
15 | * Irefs are a specific case of internal references. The value they refer to
16 | * is stored in the computation context's value store.
17 | */
18 | var Iref = record.declare(new internal_reference.InternalReference, [
19 | 'key']);
20 |
21 | Iref.prefix = "iref:";
22 |
23 | Iref.prototype.getValue = function() {
24 | return compute.getValue(Iref.prefix + this.key);
25 | };
26 |
27 | Iref.prototype.setValue = function(x) {
28 | return compute.next(
29 | compute.setValue(Iref.prefix + this.key, x),
30 | compute.just(this));
31 | };
32 |
33 | /* Export
34 | ******************************************************************************/
35 | return {
36 | 'Iref': Iref
37 | };
38 |
39 | });
--------------------------------------------------------------------------------
/lib/operations/boolean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Boolean value computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/operations/type_conversion',
8 | 'atum/value/boolean',
9 | 'atum/value/value'],
10 | function(exports,
11 | compute,
12 | fun,
13 | type_conversion,
14 | boolean,
15 | value) {
16 | "use strict";
17 |
18 | /* Creation
19 | ******************************************************************************/
20 | /**
21 | * Create a hosted boolean value.
22 | *
23 | * @param x Host value to create hosted boolean from.
24 | */
25 | exports.create = compute.from(boolean.create);
26 |
27 | /**
28 | * Create a hosted boolean value from the results of a computation.
29 | */
30 | exports.from = compute.lift(boolean.create);
31 |
32 | /* Constants
33 | ******************************************************************************/
34 | exports.TRUE = compute.just(boolean.TRUE);
35 |
36 | exports.FALSE = compute.just(boolean.FALSE);
37 |
38 | /* Host Operations
39 | ******************************************************************************/
40 | /**
41 | * Computation resulting in host boolean value of if the result of computation
42 | * `c` a true boolean hosted value.
43 | */
44 | exports.isTrue = compute.compose(
45 | type_conversion.toBoolean,
46 | compute.from(boolean.isTrue));
47 |
48 | /* Logical Operators
49 | ******************************************************************************/
50 | /**
51 | * Perform a logical not on `argument`.
52 | *
53 | * @param argument Computation resulting in hosted boolean value.
54 | */
55 | exports.logicalNot = compute.compose(
56 | type_conversion.toBoolean,
57 | compute.from(boolean.logicalNot));
58 |
59 | });
--------------------------------------------------------------------------------
/lib/operations/compare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Comparison operation computations.
3 | *
4 | * Unlike `atum/value/compare`, these also handle object values.
5 | */
6 | define(['exports',
7 | 'atum/compute',
8 | 'atum/fun',
9 | 'atum/operations/boolean',
10 | 'atum/operations/type_conversion',
11 | 'atum/operations/value_reference',
12 | 'atum/value/compare',
13 | 'atum/value/value'],
14 | function(exports,
15 | compute,
16 | fun,
17 | boolean,
18 | type_conversion,
19 | value_reference,
20 | compare,
21 | value) {
22 | "use strict";
23 |
24 | /* Operations
25 | ******************************************************************************/
26 | /**
27 | * Regular equality comparison of `left` and `right`.
28 | *
29 | * Will attempt type conversions.
30 | */
31 | var equal = function(left, right) {
32 | return compute.binary(
33 | value_reference.getValue(left),
34 | value_reference.getValue(right),
35 | function(l, r) {
36 | if (value.isObject(l) && value.isObject(r))
37 | return boolean.create(l === r);
38 | else if (value.isObject(l))
39 | return compute.bind(
40 | type_conversion.toPrimitive(undefined, left),
41 | fun.curry(equal, right));
42 | else if (value.isObject(r))
43 | return compute.bind(
44 | type_conversion.toPrimitive(undefined, right),
45 | fun.curry(equal, left));
46 | return boolean.create(compare.equal(l, r));
47 | });
48 | };
49 |
50 | /**
51 | * Strict equality comparison of `left` and `right`.
52 | *
53 | * Does not attempt type conversion.
54 | */
55 | var strictEqual = function(left, right) {
56 | return compute.binary(
57 | value_reference.getValue(left),
58 | value_reference.getValue(right),
59 | function(l, r) {
60 | return boolean.create(value.isObject(l) && value.isObject(r) ?
61 | (l === r) :
62 | compare.strictEqual(l, r));
63 | });
64 | };
65 |
66 | /* Export
67 | ******************************************************************************/
68 | exports.equal = equal;
69 | exports.strictEqual = strictEqual;
70 |
71 | });
--------------------------------------------------------------------------------
/lib/operations/construct.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Object creation operations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/builtin/meta/object',
8 | 'atum/operations/error',
9 | 'atum/operations/string',
10 | 'atum/operations/value_reference',
11 | 'atum/value/args',
12 | 'atum/value/value'],
13 | function(exports,
14 | compute,
15 | fun,
16 | meta_object,
17 | error,
18 | string,
19 | value_reference,
20 | args,
21 | value) {
22 | "use strict";
23 |
24 | /* Creation Operations
25 | ******************************************************************************/
26 | /**
27 | * Construct a new object from a constructor.
28 | *
29 | * @param callee Reference the constructor object.
30 | * @param a Arguments to pass to constructor.
31 | */
32 | var constructForward = function(callee, a) {
33 | return value_reference.dereference(callee, function(obj) {
34 | return (value.isObject(obj) ?
35 | obj.construct(callee, a) :
36 | error.typeError('construct on non object'));
37 | });
38 | };
39 |
40 | /**
41 | * Construct a new object from a constructor.
42 | *
43 | * @param callee Reference the constructor object.
44 | * @param a Array of arguments to pass to constructor.
45 | */
46 | var construct = function(callee, a) {
47 | return constructForward(callee, args.Args.create(a));
48 | };
49 |
50 | /**
51 | *
52 | */
53 | var create = fun.composen(
54 | value_reference.create,
55 | meta_object.Object.create);
56 |
57 | /* Exports
58 | ******************************************************************************/
59 | exports.constructForward = constructForward;
60 | exports.construct = construct;
61 | exports.create = create;
62 |
63 | });
--------------------------------------------------------------------------------
/lib/operations/error.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Error computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/builtin/native_errors',
8 | 'atum/operations/execution_context',
9 | 'atum/operations/construct',
10 | 'atum/operations/object',
11 | 'atum/operations/string',
12 | 'atum/operations/type_conversion'],
13 | function(exports,
14 | compute,
15 | fun,
16 | native_errors,
17 | execution_context,
18 | construct,
19 | object,
20 | string,
21 | type_conversion) {
22 | "use strict";
23 |
24 | var createError = function(type) {
25 | return function(/*...*/) {
26 | return (arguments.length ?
27 | compute.bind(
28 | string.concata(fun.map(function(x) {
29 | if (typeof x === 'string')
30 | return string.create(x);
31 | if (typeof x !== 'function')
32 | return type_conversion.toString(x);
33 | return x;
34 | }, arguments)),
35 | function(msg) {
36 | return construct.construct(type, [msg]);
37 | }) :
38 | construct.construct(type, []));
39 | };
40 | };
41 |
42 | var error = function(type) {
43 | return compute.composen(
44 | createError(type),
45 | compute.error);
46 | }
47 |
48 | /* Error Computations
49 | ******************************************************************************/
50 | /**
51 | * Error with an eval error.
52 | *
53 | * @param [msg] Optional computation giving message for error.
54 | */
55 | var evalError = error(native_errors.EvalError);
56 |
57 | /**
58 | * Error with a range error.
59 | *
60 | * @param [msg] Optional computation giving message for error.
61 | */
62 | var rangeError = error(native_errors.RangeError);
63 |
64 | /**
65 | * Error with a reference error.
66 | *
67 | * @param [msg] Optional computation giving message for error.
68 | */
69 | var referenceError = error(native_errors.ReferenceError);
70 |
71 | /**
72 | * Error with a syntax error.
73 | *
74 | * @param [msg] Optional computation giving message for error.
75 | */
76 | var syntaxError = error(native_errors.SyntaxError);
77 |
78 | /**
79 | * Error with a type error.
80 | *
81 | * @param [msg] Optional computation giving message for error.
82 | */
83 | var typeError = error(native_errors.TypeError);
84 |
85 | /**
86 | * Error with a reference error.
87 | *
88 | * @param [msg] Optional computation giving message for error.
89 | */
90 | var uriError = error(native_errors.UriError);
91 |
92 | /*
93 | ******************************************************************************/
94 | var assert = function(check, err, value) {
95 | return compute.bind(value, function(x) {
96 | return (check(x) ? compute.just(x) : err);
97 | });
98 | };
99 |
100 | /* Basic Stack Operations
101 | ******************************************************************************/
102 | /**
103 | * Gets the error handlers for the current execution context.
104 | */
105 | var getErrorHandlers = execution_context.extract(function(ctx) {
106 | return ctx.metadata.errorHandlers;
107 | });
108 |
109 | /**
110 | * Sets the error handlers to `s`
111 | */
112 | var setErrorHandlers = function(s) {
113 | return execution_context.modifyContext(function(ctx) {
114 | return ctx.setMetadata(ctx.metadata.setErrorHandlers(s));
115 | });
116 | };
117 |
118 | /**
119 | */
120 | var modifyErrorHandlers = function(f) {
121 | return compute.bind(getErrorHandlers, fun.compose(setErrorHandlers, f));
122 | };
123 |
124 | /* Stack Operations
125 | ******************************************************************************/
126 | /**
127 |
128 | */
129 | var push = function(frame) {
130 | return modifyErrorHandlers(fun.curry(fun.concat, frame));
131 | };
132 |
133 | /**
134 | */
135 | var pop = modifyErrorHandlers(fun.curry(fun.slice, 1, undefined));
136 |
137 |
138 | /* Export
139 | ******************************************************************************/
140 | exports.evalError = evalError;
141 | exports.rangeError = rangeError;
142 | exports.referenceError = referenceError;
143 | exports.syntaxError = syntaxError;
144 | exports.typeError = typeError;
145 | exports.uriError = uriError;
146 |
147 | exports.assert = assert;
148 |
149 | // Error Handlers
150 | exports.push = push;
151 | exports.pop = pop;
152 |
153 | });
--------------------------------------------------------------------------------
/lib/operations/execution_context.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Computations for interacting with the execution context.
3 | */
4 | define(['atum/compute',
5 | 'atum/fun',
6 | 'atum/context/execution_context',
7 | 'atum/context/execution_metadata'],
8 | function(compute,
9 | fun,
10 | execution_context,
11 | execution_metadata) {
12 | "use strict";
13 |
14 | /* Base Computations
15 | *
16 | * Currently these forward to `compute` but future changes may decouple the
17 | * compute execution context from the hosted language execution context.
18 | * These versions should always be used instead of the `compute` versions to
19 | * support this change.
20 | ******************************************************************************/
21 | /**
22 | * Computation to get the current execution context.
23 | */
24 | var context = compute.context;
25 |
26 | /**
27 | * Computation to modify the current execution context with `f`.
28 | */
29 | var modifyContext = compute.modifyContext;
30 |
31 | /**
32 | * Computation to set the current execution context to `ctx`.
33 | */
34 | var setContext = compute.setContext;
35 |
36 | /**
37 | * Computation to extract a value from the current execution context with `f`.
38 | */
39 | var extract = compute.extract;
40 |
41 | /* Query Computations
42 | ******************************************************************************/
43 | /**
44 | * Get the strictness of the current execution context.
45 | */
46 | var strict = extract(function(ctx) {
47 | return ctx.strict;
48 | });
49 |
50 | /**
51 | * Set the strictness of the current execution context.
52 | */
53 | var setStrict = function(isStrict) {
54 | return modifyContext(function(ctx) {
55 | return ctx.setStrict(isStrict);
56 | });
57 | };
58 |
59 | /**
60 | * Performs computation 'p' with this binding 't'.
61 | * Restore old this binding on completion.
62 | */
63 | var withStrict = function(isStrict, p) {
64 | return compute.bind(strict, function(oldStrictness) {
65 | return compute.betweenForce(setStrict(isStrict), setStrict(oldStrictness),
66 | p);
67 | });
68 | };
69 |
70 | /**
71 | * Get the this binding of the current execution context.
72 | */
73 | var thisBinding = extract(function(ctx) {
74 | return ctx.thisBinding;
75 | });
76 |
77 | /**
78 | * Modifies the this binding of the current execution context.
79 | *
80 | * @param f Function that maps current this binding to the new this binding.
81 | */
82 | var modifyThisBinding = function(f) {
83 | return modifyContext(function(ctx) {
84 | return ctx.setThisBinding(f(ctx.thisBinding));
85 | });
86 | };
87 |
88 | /**
89 | * Sets this binding of the current execution context
90 | */
91 | var setThisBinding = fun.compose(
92 | modifyThisBinding,
93 | fun.constant);
94 |
95 | /**
96 | * Performs computation 'p' with this binding 't'.
97 | * Restore old this binding on completion.
98 | */
99 | var withThisBinding = function(t, p) {
100 | return compute.bind(thisBinding, function(oldT) {
101 | return compute.betweenForce(setThisBinding(t), setThisBinding(oldT),
102 | p);
103 | });
104 | };
105 |
106 | /**
107 | * Get the current execution context's location value.
108 | */
109 | var loc = extract(function(ctx) {
110 | return ctx.metadata.loc;
111 | });
112 |
113 | /**
114 | * Set the location of the current execution contex.
115 | */
116 | var setLoc = function(loc) {
117 | return modifyContext(function(ctx) {
118 | return ctx.setMetadata(ctx.metadata.setLoc(loc));
119 | });
120 | };
121 |
122 | /* Creation
123 | ******************************************************************************/
124 | var createEvalContext = function() {
125 | return extract(function(ctx) {
126 | return ctx; // @TODO: strict mode
127 | });
128 | };
129 |
130 | /* Export
131 | ******************************************************************************/
132 | return {
133 | 'extract': extract,
134 | 'context': context,
135 | 'modifyContext': modifyContext,
136 | 'setContext': setContext,
137 |
138 | 'strict': strict,
139 | 'setStrict': setStrict,
140 | 'withStrict': withStrict,
141 |
142 | 'thisBinding': thisBinding,
143 | 'modifyThisBinding': modifyThisBinding,
144 | 'setThisBinding': setThisBinding,
145 | 'withThisBinding': withThisBinding,
146 |
147 |
148 | 'loc': loc,
149 | 'setLoc': setLoc,
150 |
151 | 'createEvalContext': createEvalContext,
152 | };
153 |
154 | });
--------------------------------------------------------------------------------
/lib/operations/execution_settings.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Operations for interacting with execution context settings.
3 | */
4 | define(['atum/fun',
5 | 'atum/context/execution_context',
6 | 'atum/operations/execution_context'],
7 | function(fun,
8 | context_execution_context,
9 | execution_context) {
10 | "use strict";
11 |
12 | /* Base Operations
13 | ******************************************************************************/
14 | /**
15 | * Computation to extract a value from the current settings with `f`.
16 | */
17 | var extract = function(f) {
18 | return execution_context.extract(function(ctx) {
19 | return f(ctx.settings);
20 | });
21 | };
22 |
23 | /**
24 | * Computation to get the current execution context settings.
25 | */
26 | var settings = extract(fun.identity);
27 |
28 | /**
29 | * Computation to modify the current execution context settings with `f`.
30 | */
31 | var modifySettings = function(f) {
32 | return execution_context.modifyContext(function(ctx) {
33 | return ctx.setSettings(f(ctx.settings));
34 | });
35 | };
36 |
37 | /**
38 | * Computation to set the current execution context settings to `settings`.
39 | */
40 | var setSettings = fun.compose(
41 | modifySettings,
42 | fun.constant);
43 |
44 | /* Query Operations
45 | ******************************************************************************/
46 | /**
47 | * Computation to get the current maximum call stack size setting.
48 | */
49 | var maxStack = extract(function(settings) {
50 | return settings.maxStack;
51 | });
52 |
53 | /* Export
54 | ******************************************************************************/
55 | return {
56 | // Base Operations
57 | 'extract': extract,
58 | 'settings': settings,
59 | 'modifySettings': modifySettings,
60 | 'setSettings': setSettings,
61 |
62 | // Query Operations
63 | 'maxStack': maxStack
64 | };
65 |
66 | });
--------------------------------------------------------------------------------
/lib/operations/internal_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Implementation level reference computations.
3 | */
4 | define(['atum/compute',
5 | 'atum/internal_reference'],
6 | function(compute,
7 | internal_reference){
8 | "use strict";
9 |
10 | /* Computations
11 | ******************************************************************************/
12 | /**
13 | * Get the value stored for ref.
14 | */
15 | var getValue = function(ref) {
16 | return (ref instanceof internal_reference.InternalReference ?
17 | ref.getValue() :
18 | compute.just(ref));
19 | };
20 |
21 | /**
22 | * Get the value stored from the result of c.
23 | */
24 | var getFrom = compute.composeWith(getValue);
25 |
26 | /**
27 | * Attempt to dereference a internal reference, continuing execution with the result of `f`.
28 | *
29 | * Calls `f` with unmodified value if `ref` is not an internal reference.
30 | *
31 | * @param ref Potential internal reference.
32 | * @param f Function called with the dereferenced result and the original reference.
33 | */
34 | var dereference = function(ref, f) {
35 | return compute.bind(getValue(ref), function(o) {
36 | return f(o, ref);
37 | });
38 | };
39 |
40 | /**
41 | * Attempt to dereference the result of computation `c`.
42 | *
43 | * @see dereference
44 | */
45 | var dereferenceFrom = function(c, f) {
46 | return compute.bind(c, function(ref) {
47 | return dereference(ref, f);
48 | });
49 | };
50 |
51 | /**
52 | * Sets the value stored for ref value to value.
53 | *
54 | * @param ref Internal reference.
55 | * @param value New value.
56 | */
57 | var setValue = function(ref, value) {
58 | return ref.setValue(value);
59 | };
60 |
61 | /**
62 | * Set ref to `f` called with ref's current value.
63 | *
64 | * @param ref Internal reference to modify.
65 | * @param f Function mapping current value to new value.
66 | */
67 | var modifyValue = function(ref, f) {
68 | return dereference(ref, function(val, ref) {
69 | return setValue(ref, f(val));
70 | });
71 | };
72 |
73 | /* Export
74 | ******************************************************************************/
75 | return {
76 | 'getValue': getValue,
77 | 'getFrom': getFrom,
78 |
79 | 'dereference': dereference,
80 | 'dereferenceFrom': dereferenceFrom,
81 |
82 | 'modifyValue': modifyValue,
83 | 'setValue': setValue
84 | };
85 |
86 | });
--------------------------------------------------------------------------------
/lib/operations/iref.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | define(['atum/compute',
5 | 'atum/iref'],
6 | function(compute,
7 | iref){
8 |
9 | /* Creation
10 | ******************************************************************************/
11 | /**
12 | * Create a computation that dereferences the result of computation 'v'.
13 | */
14 | var create = function(value) {
15 | return compute.bind(compute.unique, function(key) {
16 | return iref.Iref.create(key).setValue(value);
17 | });
18 | };
19 |
20 | /* Export
21 | ******************************************************************************/
22 | return {
23 | 'create': create
24 | };
25 |
26 | });
--------------------------------------------------------------------------------
/lib/operations/nil.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Null value computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/value/nil'],
7 | function(exports,
8 | compute,
9 | nil) {
10 | "use strict";
11 |
12 | exports.NULL = compute.just(nil.NULL);
13 |
14 | });
--------------------------------------------------------------------------------
/lib/operations/number.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Number operation computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/operations/type_conversion',
8 | 'atum/value/number'],
9 | function(exports,
10 | compute,
11 | fun,
12 | type_conversion,
13 | number) {
14 | "use strict";
15 |
16 | var _binaryOperation = function(op, leftType, rightType) {
17 | op = compute.from(op);
18 | leftType = leftType || type_conversion.toNumber;
19 | rightType = rightType || type_conversion.toNumber;
20 |
21 | return function(left, right) {
22 | return compute.binary(
23 | leftType(left),
24 | rightType(right),
25 | op);
26 | };
27 | };
28 |
29 | var _unaryOperation = function(op, type) {
30 | return compute.compose(
31 | (type || type_conversion.toNumber),
32 | compute.from(op));
33 | };
34 |
35 | /* Creation
36 | ******************************************************************************/
37 | /**
38 | * Create a hosted number value.
39 | *
40 | * @param {number} value Host language value for hosted number.
41 | */
42 | exports.create = compute.from(number.Number.create);
43 |
44 | /**
45 | * Create a new hosted number value from the results of a computation.
46 | */
47 | exports.from = compute.lift(number.Number.create);
48 |
49 | /* Constants
50 | ******************************************************************************/
51 | exports.NAN = compute.just(number.NaN);
52 |
53 | /* Host Operations
54 | ******************************************************************************/
55 | /**
56 | * Computation resulting in host number of a number value.
57 | */
58 | exports.toHost = compute.compose(
59 | type_conversion.toNumber,
60 | function(x) {
61 | return compute.just(x.value);
62 | });
63 |
64 | /* Numeric Conversion
65 | ******************************************************************************/
66 | exports.toExponential = compute.from(number.toExponential);
67 |
68 | exports.toFixed = compute.from(number.toFixed);
69 |
70 | exports.toPrecision = compute.from(number.toPrecision);
71 |
72 | /* Binary Operations
73 | ******************************************************************************/
74 | var add = _binaryOperation(number.add);
75 | exports.add = add;
76 |
77 | exports.subtract = _binaryOperation(number.subtract);
78 |
79 | exports.multiply = _binaryOperation(number.multiply);
80 |
81 | exports.divide = _binaryOperation(number.divide);
82 |
83 | exports.remainder = _binaryOperation(number.remainder);
84 |
85 | /* Bitwise Operations
86 | ******************************************************************************/
87 | exports.leftShift = _binaryOperation(number.leftShift,
88 | type_conversion.toInt32,
89 | type_conversion.toUint32);
90 |
91 | exports.signedRightShift = _binaryOperation(number.signedRightShift,
92 | type_conversion.toInt32,
93 | type_conversion.toUint32);
94 |
95 | exports.unsignedRightShift = _binaryOperation(number.unsignedRightShift,
96 | type_conversion.toInt32,
97 | type_conversion.toUint32);
98 |
99 | exports.bitwiseAnd = _binaryOperation(number.bitwiseAnd,
100 | type_conversion.toInt32,
101 | type_conversion.toInt32);
102 |
103 | exports.bitwiseXor = _binaryOperation(number.bitwiseXor,
104 | type_conversion.toInt32,
105 | type_conversion.toInt32);
106 |
107 | exports.bitwiseOr = _binaryOperation(number.bitwiseOr,
108 | type_conversion.toInt32,
109 | type_conversion.toInt32);
110 |
111 | /* Relational Binary Operations
112 | ******************************************************************************/
113 | exports.lt = _binaryOperation(number.lt);
114 |
115 | exports.lte = _binaryOperation(number.lte);
116 |
117 | exports.gt = _binaryOperation(number.gt);
118 |
119 | exports.gte = _binaryOperation(number.gte);
120 |
121 | /* Unary Operations
122 | ******************************************************************************/
123 | exports.negate = _unaryOperation(number.negate);
124 |
125 | exports.bitwiseNot = _unaryOperation(number.bitwiseNot, type_conversion.toInt32);
126 |
127 | /* Update Operation Computation
128 | ******************************************************************************/
129 | exports.increment = fun.curry(add, new number.Number(1));
130 |
131 | exports.decrement = fun.curry(add, new number.Number(-1));
132 |
133 | });
--------------------------------------------------------------------------------
/lib/operations/property.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Property operations.
3 | */
4 | define(['exports',
5 | 'bes/object',
6 | 'atum/compute',
7 | 'atum/builtin/operations/object',
8 | 'atum/operations/boolean',
9 | 'atum/operations/error',
10 | 'atum/operations/func',
11 | 'atum/operations/object',
12 | 'atum/operations/string',
13 | 'atum/operations/undef',
14 | 'atum/operations/value_reference',
15 | 'atum/value/boolean',
16 | 'atum/value/property',
17 | 'atum/value/undef',
18 | 'atum/value/value'],
19 | function(exports,
20 | amulet_object,
21 | compute,
22 | object_builtin,
23 | boolean,
24 | error,
25 | func,
26 | object,
27 | string,
28 | undef,
29 | value_reference,
30 | boolean_value,
31 | property,
32 | undef_value,
33 | value) {
34 | "use strict";
35 |
36 | /* Descriptor Operations
37 | ******************************************************************************/
38 | /**
39 | * Create a hosted object from a property descriptor.
40 | */
41 | var fromPropertyDescriptor = function(desc) {
42 | if (!desc)
43 | return undef.UNDEFINED;
44 |
45 | var properties = {
46 | 'enumerable': property.createValuePropertyFlags(
47 | boolean_value.create(desc.enumerable),
48 | property.ALL),
49 |
50 | 'configurable': property.createValuePropertyFlags(
51 | boolean_value.create(desc.configurable),
52 | property.ALL)
53 | };
54 |
55 | if (property.isDataDescriptor(desc)) {
56 | properties['value'] = property.createValuePropertyFlags(
57 | desc.value || undef_value.UNDEFINED,
58 | property.ALL);
59 |
60 | properties['writable'] = property.createValuePropertyFlags(
61 | boolean_value.create(desc.writable),
62 | property.ALL);
63 | } else {
64 | properties['get'] = property.createValuePropertyFlags(
65 | desc.get || undef_value.UNDEFINED,
66 | property.ALL);
67 |
68 | properties['set'] = property.createValuePropertyFlags(
69 | desc.set || undef_value.UNDEFINED,
70 | property.ALL);
71 | }
72 |
73 | return compute.bind(object_builtin.create(), function(obj) {
74 | return object.defineProperties(obj, properties)
75 | });
76 | };
77 | /**
78 | * Convert a hosted object to a property descriptor.
79 | *
80 | * @TODO: ugly
81 | */
82 | var toPropertyDescriptor = (function(){
83 | var getProperty = function(obj, prop, f, desc) {
84 | return compute.branch(object.hasProperty(obj, prop),
85 | compute.binds(
86 | compute.enumeration(
87 | compute.bind(object.get(obj, prop), f),
88 | desc),
89 | function(x, desc) {
90 | return compute.just(amulet_object.setProperty(desc, prop, x, true));
91 | }),
92 | desc);
93 | };
94 |
95 | var isCallable = function(ref) {
96 | return compute.branch(func.isCallable(ref),
97 | compute.just(ref),
98 | error.typeError());
99 | };
100 |
101 | return function(obj) {
102 | return value_reference.dereference(obj, function(t) {
103 | if (!value.isObject(t))
104 | return error.typeError();
105 |
106 | return compute.bind(
107 | getProperty(t, 'set', isCallable,
108 | getProperty(t, 'get', isCallable,
109 | getProperty(t, 'writable', boolean.isTrue,
110 | getProperty(t, 'value', compute.just,
111 | getProperty(t, 'configurable', boolean.isTrue,
112 | getProperty(t, 'enumerable', boolean.isTrue,
113 | compute.just(new property.Property))))))),
114 | function(desc) {
115 | if (desc.get || desc.set) {
116 | if (desc.value || desc.writable)
117 | return error.typeError();
118 | }
119 | return compute.just(desc);
120 | });
121 | });
122 | };
123 | }());
124 |
125 | /* Exports
126 | ******************************************************************************/
127 | exports.fromPropertyDescriptor = fromPropertyDescriptor;
128 | exports.toPropertyDescriptor = toPropertyDescriptor;
129 |
130 | });
--------------------------------------------------------------------------------
/lib/operations/string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview String computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/operations/type_conversion',
8 | 'atum/value/string'],
9 | function(exports,
10 | compute,
11 | fun,
12 | type_conversion,
13 | string) {
14 | "use strict";
15 |
16 | /* Constants
17 | ******************************************************************************/
18 | /**
19 | * Computation resulting in empty string;
20 | */
21 | var EMPTY = compute.just(string.EMPTY);
22 |
23 | /* Creation
24 | ******************************************************************************/
25 | /**
26 | * Create a new hosted string.
27 | *
28 | * @param {string} x Host value to store in string.
29 | */
30 | var create = compute.from(string.String.create);
31 |
32 | /**
33 | * Computation that creates a new hosted string from the result of computation x.
34 | *
35 | * @param x Computation resulting in a host string to store in string.
36 | */
37 | var from = compute.lift(string.String.create);
38 |
39 | /* Host Operations
40 | ******************************************************************************/
41 | /**
42 | * Computation resulting in host string of a string.
43 | */
44 | var toHost = function(c) {
45 | return compute.map(
46 | type_conversion.toString(c),
47 | function(x) {
48 | return x.value;
49 | });
50 | };
51 |
52 | /* Operations
53 | ******************************************************************************/
54 | /**
55 | * Concatenates `l` and `l` into a new hosted string.
56 | *
57 | * @param left Computation resulting in string value.
58 | * @param right Computation resulting in string value.
59 | */
60 | var binaryConcat = function(left, right) {
61 | return compute.binary(
62 | compute.bind(left, type_conversion.toString),
63 | compute.bind(right, type_conversion.toString),
64 | compute.from(string.concat));
65 | };
66 |
67 | /**
68 | * Concats an array of string computations to a hosted string.
69 | */
70 | var concata = fun.curry(fun.foldl, binaryConcat, EMPTY);
71 |
72 | /**
73 | * Concatenates all arguments into a new hosted string.
74 | */
75 | var concat = fun.composen(concata, fun.args);
76 |
77 | /* Export
78 | ******************************************************************************/
79 | // Constants
80 | exports.EMPTY = EMPTY;
81 |
82 | // Creation
83 | exports.create = create;
84 | exports.from = from;
85 |
86 | // Host Operations
87 | exports.toHost = toHost;
88 |
89 | // Operations
90 | exports.concata = concata;
91 | exports.concat = concat;
92 |
93 | });
--------------------------------------------------------------------------------
/lib/operations/type_conversion.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Type conversion operations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/fun',
7 | 'atum/builtin/operations/boolean',
8 | 'atum/builtin/operations/number',
9 | 'atum/builtin/operations/string',
10 | 'atum/operations/boolean',
11 | 'atum/operations/error',
12 | 'atum/operations/value_reference',
13 | 'atum/value/type',
14 | 'atum/value/type_conversion',
15 | 'atum/value/value'],
16 | function(exports,
17 | compute,
18 | fun,
19 | boolean_builtin,
20 | number_builtin,
21 | string_builtin,
22 | boolean,
23 | error,
24 | value_reference,
25 | type,
26 | type_conversion,
27 | value) {
28 | "use strict";
29 |
30 | /* Conversions
31 | ******************************************************************************/
32 | /**
33 | * Convert to a primitive value.
34 | *
35 | * @param [preferredType] Hint for type to convert to.
36 | * @param input Value to convert.
37 | */
38 | var toPrimitive = function(preferredType, input) {
39 | return value_reference.dereference(input, function(x) {
40 | return (value.isObject(x) ?
41 | x.defaultValue(input, preferredType) :
42 | compute.just(x));
43 | });
44 | };
45 |
46 | /**
47 | * Convert to a boolean.
48 | *
49 | * @param input Value to convert.
50 | */
51 | var toBoolean = function(input) {
52 | return value_reference.dereference(input, function(x) {
53 | return (value.isObject(x) ?
54 | boolean.TRUE :
55 | compute.just(type_conversion.toBoolean(x)));
56 | });
57 | };
58 |
59 | /**
60 | * Converts to a number.
61 | *
62 | * @param input Value to convert.
63 | */
64 | var toNumber = compute.compose(
65 | fun.curry(toPrimitive, type.NUMBER),
66 | compute.from(type_conversion.toNumber));
67 |
68 | /**
69 | * Convert to an integer.
70 | *
71 | * @param input Value to convert.
72 | */
73 | var toInteger = compute.compose(
74 | toNumber,
75 | compute.from(type_conversion.toInteger));
76 |
77 | /**
78 | * Convert to a signed 32 bit integer.
79 | *
80 | * @param input Value to convert.
81 | */
82 | var toInt32 = compute.compose(
83 | toNumber,
84 | compute.from(type_conversion.toInt32));
85 |
86 | /**
87 | * Convert to an unsigned 32 bit integer.
88 | *
89 | * @param input Value to convert.
90 | */
91 | var toUint32 = compute.compose(
92 | toNumber,
93 | compute.from(type_conversion.toUint32));
94 |
95 | /**
96 | * Convert to a string.
97 | *
98 | * @param input Value to convert.
99 | */
100 | var toString = compute.compose(
101 | fun.curry(toPrimitive, type.STRING),
102 | compute.from(type_conversion.toString));
103 |
104 | /**
105 | * Convert to an object.
106 | *
107 | * @param input Value to convert.
108 | */
109 | var toObject = function(input) {
110 | return value_reference.dereference(input, function(v, ref) {
111 | switch (v.type) {
112 | case type.UNDEFINED:
113 | case type.NULL:
114 | return error.typeError(v, ' cannot be converted to an object');
115 |
116 | case type.NUMBER:
117 | return number_builtin.create(ref);
118 |
119 | case type.BOOLEAN:
120 | return boolean_builtin.create(ref);
121 |
122 | case type.STRING:
123 | return string_builtin.create(ref);
124 | }
125 | return compute.just(ref);
126 | });
127 | };
128 |
129 | /* Export
130 | ******************************************************************************/
131 | exports.toPrimitive = toPrimitive;
132 | exports.toBoolean = toBoolean;
133 | exports.toNumber = toNumber;
134 | exports.toInteger = toInteger;
135 | exports.toInt32 = toInt32;
136 | exports.toUint32 = toUint32;
137 | exports.toString = toString;
138 | exports.toObject = toObject;
139 |
140 | });
--------------------------------------------------------------------------------
/lib/operations/undef.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Undefined value computations.
3 | */
4 | define(['exports',
5 | 'atum/compute',
6 | 'atum/value/undef'],
7 | function(exports,
8 | compute,
9 | undef) {
10 | "use strict";
11 |
12 | exports.UNDEFINED = compute.just(undef.UNDEFINED);
13 |
14 | });
--------------------------------------------------------------------------------
/lib/operations/value_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Implementation level reference computations.
3 | */
4 | define(['atum/compute',
5 | 'atum/value_reference'],
6 | function(compute,
7 | value_reference){
8 | "use strict";
9 |
10 | /* Creation
11 | ******************************************************************************/
12 | /**
13 | * Create a new value reference.
14 | *
15 | * @param [initial] Value to store in new reference.
16 | */
17 | var create = function(initial) {
18 | return compute.bind(compute.unique, function(key) {
19 | return setValue(
20 | value_reference.create(key),
21 | initial);
22 | });
23 | };
24 |
25 | /**
26 | * Create a new value reference, storing the result of computation p as the
27 | * initial value.
28 | */
29 | var from = compute.lift(create);
30 |
31 | /* Operations
32 | ******************************************************************************/
33 | /**
34 | * Attempt to dereference a value reference.
35 | *
36 | * Returns the input if `ref` is not a value reference.
37 | *
38 | * @param ref Potential value reference
39 | */
40 | var getValue = function(ref) {
41 | return (ref instanceof value_reference.ValueReference ?
42 | ref.getValue() :
43 | compute.just(ref));
44 | };
45 |
46 | /**
47 | * Dereference the result of a computation.
48 | */
49 | var getFrom = function(c) {
50 | return compute.bind(c, getValue);
51 | };
52 |
53 | /**
54 | * Attempt to dereference a value reference, continuing execution with the result of `f`.
55 | *
56 | * Calls `f` with unmodified value if `ref` is not a value reference.
57 | *
58 | * @param ref Potential value reference.
59 | * @param f Function called with the dereferenced result and the original reference.
60 | */
61 | var dereference = function(ref, f) {
62 | return compute.bind(getValue(ref), function(o) {
63 | return f(o, ref);
64 | });
65 | };
66 |
67 | /**
68 | * Attempt to dereference the result of computation `c`.
69 | *
70 | * @see dereference
71 | */
72 | var dereferenceFrom = function(c, f) {
73 | return compute.bind(c, function(ref) {
74 | return dereference(ref, f);
75 | });
76 | };
77 |
78 | /**
79 | * Set the value pointed to by `ref`.
80 | *
81 | * `ref` must be a value reference.
82 | *
83 | * @param ref Value reference.
84 | * @param value New value.
85 | */
86 | var setValue = function(ref, value) {
87 | return ref.setValue(value);
88 | };
89 |
90 | /**
91 | * Modify the value pointed to by `ref`.
92 | *
93 | * `ref` must be a value reference.
94 | *
95 | * @param ref Value reference.
96 | * @param f Function mapping current stored value to new value.
97 | */
98 | var modifyValue = function(ref, f) {
99 | return compute.bind(getValue(ref), function(x) {
100 | return setValue(ref, f(x));
101 | });
102 | };
103 |
104 |
105 | /* Export
106 | ******************************************************************************/
107 | return {
108 | // Creation
109 | 'create': create,
110 | 'from': from,
111 |
112 | // Operations
113 | 'getValue': getValue,
114 | 'getFrom': getFrom,
115 |
116 | 'dereference': dereference,
117 | 'dereferenceFrom': dereferenceFrom,
118 |
119 | 'modifyValue': modifyValue,
120 | 'setValue': setValue
121 | };
122 |
123 | });
--------------------------------------------------------------------------------
/lib/reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Interface for reference objects.
3 | */
4 | define([],
5 | function() {
6 | "use strict";
7 |
8 | /* Reference
9 | ******************************************************************************/
10 | /**
11 | * Interface / marker class for references.
12 | */
13 | var Reference = function() { };
14 |
15 | /**
16 | * Function that returns computation that yields value stored in reference.
17 | */
18 | Reference.prototype.getValue = null;
19 |
20 | /**
21 | * Function that takes one parameter, 'x', and returns a computation
22 | * that stores 'x' in the reference. Computation yields the reference.
23 | */
24 | Reference.prototype.setValue = null;
25 |
26 | /**
27 | * Function that compares two references.
28 | */
29 | Reference.prototype.eq = null;
30 |
31 | /* Export
32 | ******************************************************************************/
33 | return {
34 | 'Reference': Reference
35 | };
36 |
37 | });
--------------------------------------------------------------------------------
/lib/semantics/declaration.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Declaration semantics.
3 | */
4 | define(['atum/compute',
5 | 'atum/fun',
6 | 'atum/operations/environment',
7 | 'atum/operations/error',
8 | 'atum/operations/execution_context',
9 | 'atum/operations/internal_reference',
10 | 'atum/operations/undef',
11 | 'atum/semantics/func'],
12 | function(compute,
13 | fun,
14 | environment,
15 | error,
16 | execution_context,
17 | internal_reference,
18 | undef,
19 | func){
20 | "use strict";
21 |
22 | /* Semantics
23 | ******************************************************************************/
24 | /**
25 | * Variable declaration.
26 | *
27 | * @param {Array} declarations One or more computations declaring a variable.
28 | */
29 | var variableDeclaration = compute.sequencea;
30 |
31 | /**
32 | * Single variable declarator with initial value
33 | *
34 | * @param {string} id Identifier to bind to value.
35 | * @param init Computation for initial value of the bound variable.
36 | */
37 | var variableInitDeclarator = function(id, init) {
38 | return internal_reference.dereferenceFrom(init, function(value) {
39 | return environment.putMutableBinding(id, value);
40 | });
41 | };
42 |
43 | /**
44 | * Single variable declarator without initial value.
45 | *
46 | * @param {string} id Identifier to bind to value.
47 | */
48 | var variableDeclarator = fun.placeholder(variableInitDeclarator,
49 | fun._,
50 | undef.UNDEFINED);
51 |
52 | /**
53 | * Function declaration.
54 | *
55 | * @param {string} id Identifier to bind to value.
56 | * @param params Array of identifiers for this function's parameters.
57 | * @param body Computation for the body of the function.
58 | * @param strict Is the body of the function explicitly strict code.
59 | */
60 | var functionDeclaration = function(name, strict, params, code, declarations, body) {
61 | return variableInitDeclarator(
62 | name,
63 | func.fun(name, strict, params, code, declarations, body));
64 | };
65 |
66 | /* Export
67 | ******************************************************************************/
68 | return {
69 | 'variableDeclaration': variableDeclaration,
70 | 'variableInitDeclarator': variableInitDeclarator,
71 | 'variableDeclarator': variableDeclarator,
72 | 'functionDeclaration': functionDeclaration
73 | };
74 |
75 | });
--------------------------------------------------------------------------------
/lib/semantics/func.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Function semantics.
3 | */
4 | define(['exports',
5 | 'atum/completion',
6 | 'atum/compute',
7 | 'atum/compute/program',
8 | 'atum/builtin/operations/language_function',
9 | 'atum/operations/environment',
10 | 'atum/operations/execution_context',
11 | 'atum/operations/func',
12 | 'atum/operations/object',
13 | 'atum/operations/value_reference',
14 | 'atum/operations/undef'],
15 | function(exports,
16 | completion,
17 | compute,
18 | program,
19 | language_function,
20 | environment,
21 | execution_context,
22 | func,
23 | object,
24 | value_reference,
25 | undef){
26 | "use strict";
27 |
28 | /* Parts
29 | ******************************************************************************/
30 | /**
31 | * Create computation of a function body for a hosted language function
32 | *
33 | * Maps the completion result of `body` to an expression type result.
34 | *
35 | * @param body Statement type computation of the function's body.
36 | */
37 | var functionBody = function(body) {
38 | return program.bindStatement(body, function(x) {
39 | if (x instanceof completion.Completion) {
40 | switch (x.type) {
41 | case completion.ThrowCompletion.type:
42 | return compute.error(x.value);
43 |
44 | case completion.NormalCompletion.type:
45 | return undef.UNDEFINED;
46 |
47 | case completion.ReturnCompletion.type:
48 | return compute.just(x.value);
49 |
50 | case completion.BreakCompletion.type:
51 | return error.syntaxError("'break' is only valid inside a switch or loop statement");
52 |
53 | case completion.ContinueCompletion.type:
54 | return error.syntaxError("'continue' is only valid inside a loop statement");
55 | }
56 | }
57 | return compute.just(x);
58 | });
59 | };
60 |
61 | /* Function Semantics
62 | ******************************************************************************/
63 | /**
64 | * Function
65 | *
66 | * Creates a new hosted language function instance.
67 | *
68 | * @param {string} id Identifier for the function object.
69 | * @param params Array of names for the parameters the function accepts.
70 | * @param body Computation of the body of the function.
71 | * @param strict Is the body of the function strict. The resulting function may
72 | * still be strict even if the body is not explicitly strict but it is contained
73 | * in strict code.
74 | */
75 | var fun = function(id, strict, params, code, declarations, body) {
76 | return compute.binds(
77 | compute.enumeration(
78 | environment.getEnvironment,
79 | execution_context.strict),
80 | function(scope, contextStrict) {
81 | return language_function.create(
82 | scope,
83 | (contextStrict || strict),
84 | id,
85 | params,
86 | code,
87 | declarations,
88 | functionBody(body));
89 | });
90 | };
91 |
92 | /* Export
93 | ******************************************************************************/
94 | exports.functionBody = functionBody;
95 |
96 | exports.fun = fun;
97 |
98 | });
--------------------------------------------------------------------------------
/lib/semantics/program.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview ECMAScript 5.1 program semantics.
3 | */
4 | define(['exports',
5 | 'atum/completion',
6 | 'atum/compute',
7 | 'atum/fun',
8 | 'atum/compute/statement',
9 | 'atum/compute/program',
10 | 'atum/builtin/impl/global',
11 | 'atum/builtin/operations/global',
12 | 'atum/semantics/statement',
13 | 'atum/operations/declaration_binding',
14 | 'atum/operations/environment',
15 | 'atum/operations/error',
16 | 'atum/operations/execution_context',
17 | 'atum/operations/undef'],
18 | function(exports,
19 | completion,
20 | compute,
21 | fun,
22 | statement,
23 | program_computations,
24 | global,
25 | global_ops,
26 | statement_semantics,
27 | declaration_binding,
28 | environment,
29 | error,
30 | execution_context,
31 | undef){
32 | "use strict";
33 |
34 | var extract = function(x) {
35 | if (x instanceof completion.Completion) {
36 | switch (x.type) {
37 | case completion.NormalCompletion.type:
38 | return (x.value === null ? undef.UNDEFINED : compute.just(x.value));
39 |
40 | case completion.ReturnCompletion.type:
41 | return error.syntaxError("Return statements are only valid inside functions");
42 |
43 | case completion.BreakCompletion.type:
44 | return error.syntaxError("'break' is only valid inside a switch or loop statement");
45 |
46 | case completion.ContinueCompletion.type:
47 | return error.syntaxError("'continue' is only valid inside a loop statement");
48 |
49 | case completion.ThrowCompletion.type:
50 | return compute.error(x.value);
51 | }
52 | }
53 | return compute.just(x);
54 | };
55 |
56 | /* Semantics
57 | ******************************************************************************/
58 | var sourceElementsDeclarations = fun.compose(
59 | statement_semantics.statementList,
60 | fun.curry(fun.map, statement.liftExpression));
61 |
62 | var sourceElementsStatements = statement_semantics.statementList;
63 |
64 | var sourceBody = function(strict, body) {
65 | return (strict ?
66 | execution_context.withStrict(strict, body) :
67 | body);
68 | };
69 |
70 | /**
71 | * Semantics for the body of a program or function.
72 | *
73 | * Evaluates statements in order until a completion is found or no more statements
74 | * are left.
75 | *
76 | * @param strict Is this block explicitly strict. False inherits strictness from
77 | * current environment.
78 | * @param declarations Array of declarations to evaluate before evaluating any
79 | * statements.
80 | * @param statements Array of statement computations to evaluate in order.
81 | */
82 | var sourceElements = function(strict, declarations, statements) {
83 | return sourceBody(
84 | strict,
85 | statement.next(
86 | statement.liftExpression(
87 | compute.bind(
88 | environment.getEnvironment,
89 | function(env) {
90 | return declaration_binding.initGlobal(env, strict, declarations);
91 | })),
92 | sourceElementsStatements(statements)));
93 | };
94 |
95 | /**
96 | * Semantics for the body of a program.
97 | *
98 | * When body results in a completion, the completion value is extracted.
99 | */
100 | var programBody = function(body) {
101 | return program_computations.bindStatement(body, extract);
102 | };
103 |
104 | /**
105 | * Program semantics.
106 | *
107 | * Initializes the execution context and evaluates the body of the program.
108 | */
109 | var program = function(body) {
110 | return compute.sequence(
111 | global.initialize(),
112 | global_ops.enterGlobal(),
113 | programBody(body));
114 | };
115 |
116 | /* Export
117 | ******************************************************************************/
118 | exports.extract = extract;
119 |
120 | exports.sourceBody = sourceBody;
121 | exports.sourceElements = sourceElements;
122 |
123 | exports.program = program;
124 | exports.programBody = programBody;
125 |
126 | });
--------------------------------------------------------------------------------
/lib/value/args.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Internal arguments object.
3 | */
4 | define(['bes/record',
5 | 'atum/fun',
6 | 'atum/value/undef'],
7 | function(record,
8 | fun,
9 | undef) {
10 | "use strict";
11 |
12 | /* Args
13 | ******************************************************************************/
14 | /**
15 | * Internal object used for representing a list of function arguments.
16 | *
17 | * Args objects should always be used instead of arrays because they correctly
18 | * handled accessing undefined argument values.
19 | */
20 | var Args = record.declare(null, [
21 | 'args'],
22 | function(args) {
23 | this.args = args;
24 | this.length = (args ? args.length : 0);
25 | });
26 |
27 | Args.prototype.getArg = function(i) {
28 | return (i >= 0 && i < this.length ?
29 | this.args[i] :
30 | undef.UNDEFINED);
31 | };
32 |
33 | Args.prototype.slice = function(/*...*/) {
34 | return Args.create([].slice.apply(this.args, arguments));
35 | };
36 |
37 | Args.prototype.reduce = function(f, z) {
38 | return fun.foldl(f, z, this.args);
39 | };
40 |
41 | Args.prototype.append = function(value) {
42 | return Args.create(this.args.concat([value]));
43 | };
44 |
45 | Args.prototype.concat = function(a) {
46 | return Args.create(this.args.concat(a.args));
47 | };
48 |
49 | /* Export
50 | ******************************************************************************/
51 | return {
52 | 'Args': Args
53 | };
54 |
55 | });
--------------------------------------------------------------------------------
/lib/value/boolean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Boolean primitive value and operations.
3 | */
4 | define(['bes/record',
5 | 'atum/value/type',
6 | 'atum/value/value'],
7 | function(record,
8 | type,
9 | value) {
10 | "use strict";
11 |
12 | /* Boolean
13 | ******************************************************************************/
14 | /**
15 | * Boolean primitive value.
16 | */
17 | var Boolean = record.extend(value.Value, [
18 | 'value']);
19 |
20 | Boolean.prototype.type = type.BOOLEAN;
21 |
22 | /* Constants
23 | ******************************************************************************/
24 | var FALSE = Boolean.create(false);
25 |
26 | var TRUE = Boolean.create(true);
27 |
28 | /* Operations
29 | ******************************************************************************/
30 | var create = function(x) {
31 | return (x ? TRUE : FALSE);
32 | };
33 |
34 | var isTrue = function(x) {
35 | return (value.isBoolean(x) && x.value);
36 | };
37 |
38 | /* Logical Operations
39 | ******************************************************************************/
40 | var logicalNot = function(a) {
41 | return create(!a.value);
42 | };
43 |
44 | /* Export
45 | ******************************************************************************/
46 | return {
47 | 'create': create,
48 |
49 | // Constants
50 | 'FALSE': FALSE,
51 | 'TRUE': TRUE,
52 |
53 | // Operations
54 | 'isTrue': isTrue,
55 |
56 | // Logical Operations
57 | 'logicalNot': logicalNot
58 | };
59 |
60 | });
--------------------------------------------------------------------------------
/lib/value/compare.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Comparison operations for primitive values.
3 | *
4 | * Does not handle object values.
5 | */
6 | define(['atum/value/type',
7 | 'atum/value/type_conversion'],
8 | function(type,
9 | type_conversion) {
10 | "use strict";
11 |
12 | /* Compare Operations
13 | ******************************************************************************/
14 | /**
15 | * Perform a strict equality comparison of primitive values 'x' and 'y'.
16 | *
17 | * Does not perform type conversion.
18 | *
19 | * @return Host boolean.
20 | */
21 | var strictEqual = function(x, y) {
22 | if (x.type !== y.type)
23 | return false;
24 |
25 | switch (x.type) {
26 | case type.UNDEFINED:
27 | case type.NULL:
28 | return true;
29 | default:
30 | return (x.value === y.value);
31 | }
32 | };
33 |
34 | /**
35 | * Perform a equality comparison on primitive values 'x' and 'y'.
36 | *
37 | * Attempts type conversion.
38 | *
39 | * @return Host boolean.
40 | */
41 | var equal = function(x, y) {
42 | if (x.type === y.type)
43 | return strictEqual(x, y);
44 |
45 | if ((x.type === type.NULL && y.type === type.UNDEFINED) ||
46 | (x.type === type.UNDEFINED && y.type === type.NULL)) {
47 | return true;
48 | } else if (x.type === type.NUMBER && y.type === type.STRING) {
49 | return equal(x, type_conversion.toNumber(y));
50 | } else if (x.type === type.STRING && y.type === type.NUMBER) {
51 | return equal(type_conversion.toNumber(x), y);
52 | } else if (x.type === type.BOOLEAN) {
53 | return equal(type_conversion.toNumber(x), y);
54 | } else if (y.type === type.BOOLEAN) {
55 | return equal(x, type_conversion.toNumber(y));
56 | }
57 |
58 | return false;
59 | };
60 |
61 | /* Export
62 | ******************************************************************************/
63 | return {
64 | 'equal': equal,
65 | 'strictEqual': strictEqual
66 | };
67 |
68 | });
--------------------------------------------------------------------------------
/lib/value/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Math constants and operations
3 | */
4 | var hostMath = Math;
5 |
6 | define(['exports',
7 | 'atum/value/number'],
8 | function(exports,
9 | number) {
10 | "use strict";
11 |
12 | /* Constants
13 | ******************************************************************************/
14 | exports.E = number.Number.create(hostMath.E);
15 | exports.LN10 = number.Number.create(hostMath.LN10);
16 | exports.LN2 = number.Number.create(hostMath.LN2);
17 | exports.LOG2E = number.Number.create(hostMath.LOG2E);
18 | exports.LOG10E = number.Number.create(hostMath.LOG10E);
19 | exports.PI = number.Number.create(hostMath.PI);
20 | exports.SQRT1_2 = number.Number.create(hostMath.SQRT1_2);
21 | exports.SQRT2 = number.Number.create(hostMath.SQRT2);
22 |
23 | });
--------------------------------------------------------------------------------
/lib/value/nil.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Null primitive value.
3 | */
4 | define(['bes/record',
5 | 'atum/value/type',
6 | 'atum/value/value'],
7 | function(record,
8 | type,
9 | value) {
10 | "use strict";
11 |
12 | /* Null
13 | ******************************************************************************/
14 | /**
15 | * Null primitive value.
16 | */
17 | var Null = record.extend(value.Value,
18 | []);
19 |
20 | Null.prototype.value = null;
21 | Null.prototype.type = type.NULL;
22 |
23 | /* Constants
24 | ******************************************************************************/
25 | var NULL = Null.create();
26 |
27 | /* Export
28 | ******************************************************************************/
29 | return {
30 | 'Null': Null,
31 |
32 | // Constants
33 | 'NULL': NULL
34 | };
35 |
36 | });
--------------------------------------------------------------------------------
/lib/value/object.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | var getOwnPropertyNames = Object.getOwnPropertyNames;
5 | var keys = Object.keys;
6 |
7 | define(['bes/record',
8 | 'bes/object',
9 | 'atum/value/type',
10 | 'atum/value/value'],
11 | function(record,
12 | amulet_object,
13 | type,
14 | value) {
15 | "use strict";
16 |
17 | /* Object
18 | ******************************************************************************/
19 | /**
20 | *
21 | */
22 | var Object = record.extend(value.Value, [
23 | 'proto',
24 | 'properties',
25 | 'extensible'],
26 | function(proto, properties, extensible) {
27 | this.proto = proto;
28 | this.properties = properties;
29 | this.extensible = extensible;
30 | });
31 |
32 | Object.prototype.type = type.OBJECT;
33 |
34 | /**
35 | * Host toString conversion.
36 | */
37 | Object.prototype.toString = function() {
38 | return "{object " + this.cls + "}";
39 | };
40 |
41 | /**
42 | * Get a list of names for all properties this object has.
43 | */
44 | Object.prototype.getOwnPropertyNames = function(propertyName) {
45 | return getOwnPropertyNames(this.properties);
46 | };
47 |
48 | /**
49 | * Does this object have a property `name`?
50 | *
51 | * Only checks this object, not prototype chain.
52 | *
53 | * @param {String} name Property name.
54 | */
55 | Object.prototype.hasOwnProperty = function(propertyName) {
56 | return (this.getOwnPropertyNames().indexOf(propertyName) >= 0);
57 | };
58 |
59 | /**
60 | * Returns the property descriptor for property 'name'.
61 | *
62 | * Only checks this object, not prototype. Return null if this object does
63 | * not have property.
64 | *
65 | * @param {String} name Property name.
66 | */
67 | Object.prototype.getOwnProperty = function(propertyName) {
68 | return (this.hasOwnProperty(propertyName) ?
69 | this.properties[propertyName] :
70 | null);
71 | };
72 |
73 | /**
74 | * Get a list of all enumerable property names for this object.
75 | */
76 | Object.prototype.getEnumerableProperties = function() {
77 | var self = this;
78 | return this.getOwnPropertyNames().filter(function(x) {
79 | return self.getOwnProperty(x).enumerable;
80 | });
81 | };
82 |
83 | /**
84 | * Set a property.
85 | *
86 | * Return a copy of this object with the property set.
87 | */
88 | Object.prototype.setProperty = function(name, desc) {
89 | return this.setProperties(
90 | amulet_object.setProperty(this.properties, name, desc, true));
91 | };
92 | /**
93 | * Removed a property.
94 | *
95 | * Return a copy of this object with the property removed.
96 | */
97 | Object.prototype.removeProperty = function(name) {
98 | return this.setProperties(
99 | amulet_object.deleteProperty(this.properties, name));
100 | };
101 |
102 | /* Export
103 | ******************************************************************************/
104 | return {
105 | 'Object': Object
106 | };
107 |
108 | });
--------------------------------------------------------------------------------
/lib/value/property.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | define(['bes/record'],
5 | function(record) {
6 | "use strict";
7 |
8 | var hasProperty = function(x, name) {
9 | return x[name] !== undefined;
10 | };
11 |
12 | /* Flags
13 | ******************************************************************************/
14 | var ENUMERABLE = 1 << 0,
15 | CONFIGURABLE = 1 << 1,
16 | WRITABLE = 1 << 2;
17 |
18 | var ALL = ENUMERABLE | CONFIGURABLE | WRITABLE;
19 |
20 | /* Property
21 | ******************************************************************************/
22 | var Property = record.declare(null, [
23 | 'enumerable',
24 | 'configurable',
25 | 'value',
26 | 'writable',
27 | 'get',
28 | 'set']);
29 |
30 | /* Creation
31 | ******************************************************************************/
32 | var createValueProperty = function(value, enumerable, writable, configurable) {
33 | return Property.create(
34 | !!enumerable,
35 | !!configurable,
36 | value,
37 | !!writable,
38 | undefined,
39 | undefined);
40 | };
41 |
42 | var createValuePropertyFlags = function(value, flags) {
43 | return createValueProperty(
44 | value,
45 | flags & ENUMERABLE,
46 | flags & WRITABLE,
47 | flags & CONFIGURABLE);
48 | };
49 |
50 | var createAccessorProperty = function(getter, setter, enumerable, configurable) {
51 | return Property.create(
52 | !!enumerable,
53 | !!configurable,
54 | undefined,
55 | undefined,
56 | getter,
57 | setter);
58 | };
59 |
60 | var createAccessorPropertyFlags = function(getter, setter, flags) {
61 | return createAccessorProperty(
62 | getter,
63 | setter,
64 | flags & ENUMERABLE,
65 | flags & CONFIGURABLE);
66 | };
67 |
68 | /* Queries
69 | ******************************************************************************/
70 | var isAccessorDescriptor = function(desc) {
71 | return desc && (hasProperty(desc, 'get') || hasProperty(desc, 'set'));
72 | };
73 |
74 | var isDataDescriptor = function(desc) {
75 | return desc && (hasProperty(desc, 'value') || hasProperty(desc, 'writable'));
76 | };
77 |
78 | var isGenericDescriptor = function(desc) {
79 | return desc && !isAccessorDescriptor(desc) && !isDataDescriptor(desc);
80 | };
81 |
82 | var hasGetter = function(desc) {
83 | return isAccessorDescriptor(desc) && desc.get;
84 | };
85 |
86 | var hasSetter = function(desc) {
87 | return isAccessorDescriptor(desc) && desc.set;
88 | };
89 |
90 | var areDataDescriptorEqual = function(d1, d2) {
91 | return (d1.configurable == d2.configurable &&
92 | d1.enumerable == d2.enumerable &&
93 | d1.writable && d2.writable);
94 | };
95 |
96 | /* Export
97 | ******************************************************************************/
98 | return {
99 | 'ENUMERABLE': ENUMERABLE,
100 | 'CONFIGURABLE': CONFIGURABLE,
101 | 'WRITABLE': WRITABLE,
102 | 'ALL': ALL,
103 |
104 | 'Property': Property,
105 |
106 | 'createValueProperty': createValueProperty,
107 | 'createValuePropertyFlags': createValuePropertyFlags,
108 | 'createAccessorProperty': createAccessorProperty,
109 | 'createAccessorPropertyFlags': createAccessorPropertyFlags,
110 |
111 | 'isAccessorDescriptor': isAccessorDescriptor,
112 | 'isDataDescriptor': isDataDescriptor,
113 | 'isGenericDescriptor': isGenericDescriptor,
114 |
115 | 'hasGetter': hasGetter,
116 | 'hasSetter': hasSetter,
117 |
118 | 'areDataDescriptorEqual': areDataDescriptorEqual
119 | };
120 |
121 | });
--------------------------------------------------------------------------------
/lib/value/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Primitive regular expression operations.
3 | */
4 | define([],
5 | function() {
6 | "use strict";
7 |
8 | /* Operations
9 | ******************************************************************************/
10 | /**
11 | * Match a regular expression against a string.
12 | *
13 | * @param str Hosted string to match against.
14 | * @param regexp Host regular expression used for matching.
15 | *
16 | * @return Host array of hosted string matches. May be empty.
17 | */
18 | var match = function(str, regexp) {
19 | return (str.value.match(regexp) || []);
20 | };
21 |
22 | /**
23 | * Replace all occurrences of `search` in `str` with `replacement`.
24 | *
25 | * @param str Hosted string operated on.
26 | * @param search Hosted string to search for in `str`.
27 | * @param replacement Hosted string to replace found values with.
28 | *
29 | * @return Hosted string.
30 | */
31 | var splitString = function(str, search) {
32 | var found = [];
33 | str.value.replace(search.value, function(match /*, ...*/) {
34 | found.push([].slice.call(arguments));
35 | });
36 | var last = 0;
37 | var arr = found.reduce(function(p, c) {
38 | var next = c[c.length - 2];
39 | var z = p.concat([[str.value.slice(last, next)]], [c]);
40 | last = next + c[0].length;
41 | return z;
42 | }, []);
43 | return arr.concat([[str.value.slice(last)]]);
44 | };
45 |
46 | /**
47 | *
48 | */
49 | var splitRegexp = function(str, regexp, replacement) {
50 | var found = [];
51 | str.value.replace(regexp, function(match /*, ...*/) {
52 | found.push([].slice.call(arguments));
53 | });
54 | var last = 0;
55 | var arr = found.reduce(function(p, c) {
56 | var next = c[c.length - 2];
57 | var z = p.concat([[str.value.slice(last, next)]], [c]);
58 | last = next + c[0].length;
59 | return z;
60 | }, []);
61 | return arr.concat([[str.value.slice(last)]]);}
62 |
63 | /* Export
64 | ******************************************************************************/
65 | return {
66 | 'match': match,
67 | 'splitString': splitString,
68 | 'splitRegexp': splitRegexp
69 | };
70 |
71 | });
--------------------------------------------------------------------------------
/lib/value/string.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Primitive string value and string operations.
3 | */
4 | define(['exports',
5 | 'bes/record',
6 | 'atum/value/number',
7 | 'atum/value/type',
8 | 'atum/value/value'],
9 | function(exports,
10 | record,
11 | number,
12 | type,
13 | value) {
14 | "use strict";
15 |
16 | /* String
17 | ******************************************************************************/
18 | /**
19 | * Primitive string value.
20 | *
21 | * @param {string} [v] String value stored in the primitive.
22 | */
23 | var String = record.extend(value.Value, [
24 | 'value'],
25 | function(v) {
26 | this.value = (v === undefined ? '' : v + '');
27 | });
28 |
29 | String.prototype.type = type.STRING;
30 |
31 | /* Constants
32 | ******************************************************************************/
33 | var EMPTY = String.create('');
34 |
35 | /* Operations
36 | ******************************************************************************/
37 | /**
38 | * Joins two strings into a new string.
39 | *
40 | * @return New primitive string value of string 'a' joined to string 'b'.
41 | */
42 | var concat = function(l, r) {
43 | return String.create(l.value + r.value);
44 | };
45 |
46 | /**
47 | * Get the length of a string.
48 | *
49 | * @param s Hosted string value.
50 | *
51 | * @return Hosted number.
52 | */
53 | var length = function(s) {
54 | return number.Number.create(s.value.length);
55 | };
56 |
57 | /**
58 | * Get the character at `index` in string `s`
59 | *
60 | * Index must be lt the length of the string.
61 | *
62 | * @param s Hosted string value.
63 | * @param {Number} index
64 | *
65 | * @return Hosted string of the character.
66 | */
67 | var charAt = function(s, index) {
68 | return String.create(s.value.charAt(index));
69 | };
70 |
71 | /**
72 | * Get the character code of the character at `index` in string `s`
73 | *
74 | * Index must be lt the length of the string.
75 | *
76 | * @param s Hosted string value.
77 | * @param {Number} index
78 | *
79 | * @return Hosted number of the character
80 | */
81 | var charCodeAt = function(s, index) {
82 | return number.Number.create(s.value.charCodeAt(index));
83 | };
84 |
85 | var indicies = function(s) {
86 | var names = [];
87 | for (var i = 0; i < s.value.length; ++i)
88 | names.push(i + '');
89 | return names;
90 | };
91 |
92 | /* Export
93 | ********************************************************************** ********/
94 | exports.String = String;
95 |
96 | // Constants
97 | exports.EMPTY = EMPTY;
98 |
99 | // Operations
100 | exports.concat = concat;
101 | exports.charAt = charAt;
102 | exports.charCodeAt = charCodeAt;
103 | exports.indicies = indicies;
104 | exports.length = length;
105 |
106 | });
--------------------------------------------------------------------------------
/lib/value/type.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Primitive value types.
3 | */
4 | define(['exports'], function(exports) {
5 | "use strict";
6 |
7 | exports.BOOLEAN = 'boolean';
8 | exports.NULL = 'null';
9 | exports.NUMBER = 'number';
10 | exports.OBJECT = 'object';
11 | exports.STRING = 'string';
12 | exports.UNDEFINED = 'undefined';
13 |
14 | });
--------------------------------------------------------------------------------
/lib/value/type_conversion.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Value type conversion logic.
3 | *
4 | * These conversions only handle primitive types, not objects.
5 | * 'atum/operations/type_conversion' exposes computations that also handle
6 | * object values.
7 | */
8 | define(['atum/value/boolean',
9 | 'atum/value/number',
10 | 'atum/value/object',
11 | 'atum/value/string',
12 | 'atum/value/type'],
13 | function(boolean,
14 | number,
15 | object,
16 | string,
17 | type) {
18 | "use strict";
19 |
20 | var sign = function(num) {
21 | return (num ?
22 | (num < 0 ? -1 : 1):
23 | 0);
24 | };
25 |
26 | /* Conversion
27 | ******************************************************************************/
28 | /**
29 | * Convert to a hosted boolean.
30 | */
31 | var toBoolean = function(input) {
32 | switch (input.type) {
33 | case type.BOOLEAN:
34 | return input;
35 | case type.NUMBER:
36 | return boolean.create(input.value !== 0 && input.value !== number.NaN.value);
37 | case type.STRING:
38 | return boolean.create(input.value.length > 0);
39 | case type.UNDEFINED:
40 | case type.NULL:
41 | default:
42 | return boolean.FALSE;
43 | }
44 | };
45 |
46 | /**
47 | * Convert to a hosted number.
48 | */
49 | var toNumber = function(input) {
50 | switch (input.type) {
51 | case type.NUMBER: return input;
52 | case type.UNDEFINED: return number.NaN;
53 | case type.BOOLEAN: return number.Number.create(input.value ? 1 : 0);
54 | case type.STRING: return number.Number.create(+input.value);
55 | case type.NULL:
56 | default: return number.ZERO;
57 | }
58 | };
59 |
60 | /**
61 | * Convert a number to a hosted integer.
62 | *
63 | * @param input Hosted number value.
64 | */
65 | var toInteger = function(input) {
66 | var val = input.value;
67 | switch (val) {
68 | case number.NaN.value:
69 | return number.ZERO;
70 | case number.ZERO.value:
71 | case number.POSITIVE_INFINITY.value:
72 | case number.NEGATIVE_INFINITY.value:
73 | return input;
74 | default:
75 | return number.Number.create(sign(val) * Math.floor(Math.abs(val)));
76 | }
77 | };
78 |
79 | /**
80 | * Convert a number to a hosted signed 32bit integer.
81 | *
82 | * @param input Hosted number value.
83 | */
84 | var toInt32 = function(num) {
85 | var val = num.value;
86 | switch (val) {
87 | case number.NaN.value:
88 | case number.ZERO.value:
89 | case number.POSITIVE_INFINITY.value:
90 | case number.NEGATIVE_INFINITY.value:
91 | return number.ZERO;
92 | default:
93 | var int32bit = (sign(val) * Math.floor(Math.abs(val))) % Math.pow(2, 32);
94 | return number.Number.create(int32bit >= Math.pow(2, 31) ?
95 | int32bit - Math.pow(2, 32) :
96 | int32bit);
97 | }
98 | };
99 |
100 | /**
101 | * Convert a number to a hosted unsigned 32bit integer.
102 | *
103 | * @param input Hosted number value.
104 | */
105 | var toUint32 = function(num) {
106 | var val = num.value;
107 | switch (val) {
108 | case number.NaN.value:
109 | case number.ZERO.value:
110 | case number.POSITIVE_INFINITY.value:
111 | case number.NEGATIVE_INFINITY.value:
112 | return number.ZERO;
113 | default:
114 | return number.Number.create(
115 | (sign(val) * Math.floor(Math.abs(val))) % Math.pow(2, 32));
116 | }
117 | };
118 |
119 | /**
120 | * Convert to a hosted string.
121 | */
122 | var toString = function(input) {
123 | switch (input.type) {
124 | case type.UNDEFINED: return string.String.create("undefined");
125 | case type.NULL: return string.String.create("null");
126 | case type.BOOLEAN: return string.String.create(boolean.isTrue(input) ? 'true' : 'false');
127 | case type.NUMBER: return string.String.create("" + input.value);
128 | case type.STRING: return input;
129 | default: return string.EMPTY;
130 | }
131 | };
132 |
133 | /* Export
134 | ******************************************************************************/
135 | return {
136 | 'toBoolean': toBoolean,
137 | 'toNumber': toNumber,
138 | 'toInteger': toInteger,
139 | 'toInt32': toInt32,
140 | 'toUint32': toUint32,
141 | 'toString': toString
142 | };
143 |
144 | });
--------------------------------------------------------------------------------
/lib/value/undef.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Undefined primitive value.
3 | */
4 | define(['bes/record',
5 | 'atum/value/type',
6 | 'atum/value/value'],
7 | function(record,
8 | type,
9 | value) {
10 | "use strict";
11 |
12 | /* Undefined
13 | ******************************************************************************/
14 | /**
15 | * Undefined primitive value.
16 | */
17 | var Undefined = record.extend(value.Value,
18 | []);
19 |
20 | Undefined.prototype.type = type.UNDEFINED;
21 |
22 | /* Constants
23 | ******************************************************************************/
24 | var UNDEFINED = Undefined.create();
25 |
26 | /* Export
27 | ******************************************************************************/
28 | return {
29 | 'Undefined': Undefined,
30 |
31 | // Constants
32 | 'UNDEFINED': UNDEFINED
33 | };
34 |
35 | });
--------------------------------------------------------------------------------
/lib/value/value.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview
3 | */
4 | define(['bes/record',
5 | 'atum/value/type'],
6 | function(record,
7 | types) {
8 | "use strict";
9 |
10 | /* Value
11 | ******************************************************************************/
12 | /**
13 | * Base class for a primitive value in the interpreted language.
14 | */
15 | var Value = record.declare(null, []);
16 |
17 | Value.prototype.toString = function() {
18 | return "{" + this.type + " " + this.value + "}";
19 | };
20 |
21 | /* Operations
22 | ******************************************************************************/
23 | var isType = function(t) {
24 | return function(x) {
25 | return (x.type === t);
26 | };
27 | };
28 |
29 | var isBoolean = isType(types.BOOLEAN);
30 |
31 | var isNull = isType(types.NULL);
32 |
33 | var isNumber = isType(types.NUMBER);
34 |
35 | var isObject = isType(types.OBJECT);
36 |
37 | var isString = isType(types.STRING);
38 |
39 | var isUndefined = isType(types.UNDEFINED);
40 |
41 | var isPrimitive = function(x) {
42 | return !isObject(x);
43 | };
44 |
45 | var isCallable = function(v) {
46 | switch(v.type) {
47 | case types.OBJECT: return !!v.call;
48 | default: return false;
49 | }
50 | };
51 |
52 | /* Export
53 | ******************************************************************************/
54 | return {
55 | 'Value': Value,
56 |
57 | 'isBoolean': isBoolean,
58 | 'isNull': isNull,
59 | 'isNumber': isNumber,
60 | 'isObject': isObject,
61 | 'isString': isString,
62 | 'isUndefined': isUndefined,
63 | 'isPrimitive': isPrimitive,
64 |
65 | 'isCallable': isCallable
66 | };
67 |
68 | });
--------------------------------------------------------------------------------
/lib/value_reference.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileOverview Language level reference type.
3 | */
4 | define(['atum/compute',
5 | 'atum/reference',
6 | 'atum/iref'],
7 | function(compute,
8 | reference,
9 | iref){
10 | "use strict";
11 |
12 | /* Value Reference
13 | ******************************************************************************/
14 | /**
15 | * Language level reference type.
16 | * Value references are used to represent hosted language object references.
17 | *
18 | * @param ref Internal reference the value reference points to.
19 | */
20 | var ValueReference = function(ref) {
21 | this.ref = ref;
22 | };
23 | ValueReference.prototype = new reference.Reference;
24 |
25 | ValueReference.prototype.toString = function() {
26 | return "{ValueReference " + this.ref.key + "}";
27 | };
28 |
29 | ValueReference.prototype.getValue = function() {
30 | return this.ref.getValue();
31 | };
32 |
33 | ValueReference.prototype.setValue = function(value) {
34 | return compute.next(
35 | this.ref.setValue(value),
36 | compute.just(this));
37 | };
38 |
39 | /* Operations
40 | ******************************************************************************/
41 | /**
42 | * Create a new value reference pointing to a new unique internal store.
43 | */
44 | var create = function(key) {
45 | return new ValueReference(iref.Iref.create(key));
46 | };
47 |
48 | /* Export
49 | ******************************************************************************/
50 | return {
51 | 'ValueReference': ValueReference,
52 |
53 | 'create': create
54 | };
55 |
56 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "atum",
3 | "version": "0.0.0",
4 | "description": "Functional Javascript Interpreter",
5 | "main": "",
6 | "repository": {
7 | "type": "git",
8 | "url": "git@github.com:mattbierner/atum.git"
9 | },
10 | "keywords": [
11 | 'javascript',
12 | 'functional',
13 | 'interpreter'
14 | ],
15 | "author": "Matt Bierner",
16 | "license": "MIT"
17 | }
18 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Start simple webserver so require text files are loaded correctly.
3 | */
4 | var connect = require('connect');
5 | connect.createServer(
6 | connect.static(__dirname)
7 | ).listen(8080);
--------------------------------------------------------------------------------
/test/builtin/testBoolean.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | var Boolean = $.Id('Boolean');
11 |
12 | return {
13 | 'module': "Builtin Boolean",
14 | 'tests': [
15 | ["Boolean(x) converts to boolean",
16 | function(){
17 | [[$.Boolean(true), true],
18 | [$.String(""), false],
19 | [$.String('abc'), true],
20 | [$.Object(), true]].forEach(function(x){
21 | expect.run(
22 | $.Program(
23 | $.Expression(
24 | $.Call(Boolean, [x[0]]))))
25 |
26 | .testResult()
27 | .type('boolean', x[1]);
28 | });
29 | }],
30 | ["new Boolean() unboxes to false.",
31 | function(){
32 | expect.run(
33 | $.Program(
34 | $.Expression(
35 | $.Add($.New(Boolean, []), $.String('')))))
36 |
37 | .testResult()
38 | .type('string', 'false');
39 | }],
40 | ["Set on Boolean",
41 | function(){
42 | expect.run(
43 | $.Program(
44 | $.Expression(
45 | $.Assign(a, $.New(Boolean, []))),
46 | $.Expression(
47 | $.Assign($.Member(a, b), $.String('abc')))))
48 |
49 | .test($.Expression($.Add(a, $.Member(a, b))))
50 | .type('string', 'falseabc');
51 | }],
52 | ["`Boolean.prototype.valueOf`",
53 | function(){
54 | expect.run(
55 | $.Program(
56 | $.Expression(
57 | $.Assign(a, $.New(Boolean, [$.Boolean(true)]))),
58 | $.Expression(
59 | $.Assign(b, $.Boolean(true)))))
60 |
61 | .test($.Expression($.Call($.Member(a, $.Id('valueOf')), [])))
62 | .type('boolean', true)
63 |
64 | .test(
65 | $.Expression(
66 | $.Call(
67 | $.Member($.Member($.Member(Boolean, $.Id('prototype')), $.Id('valueOf')), $.Id('call')),
68 | [b])))
69 | .type('boolean', true);
70 | }],
71 | ]
72 | };
73 | });
74 |
--------------------------------------------------------------------------------
/test/builtin/testBuiltins.js:
--------------------------------------------------------------------------------
1 | define(['builtin/testArguments',
2 | 'builtin/testBoolean',
3 | 'builtin/testFunction',
4 | 'builtin/testNumber',
5 | 'builtin/testObject',
6 | 'builtin/testString'],
7 | function() {
8 | Array.prototype.forEach.call(arguments, function(m) {
9 | m.module && module(m.module);
10 | m.tests.forEach(function(e){ test.apply(this, e); });
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/builtin/testNumber.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | var Number = $.Id('Number');
11 |
12 | return {
13 | 'module': "Builtin Number",
14 | 'tests': [
15 | ["Number(x) converts to number",
16 | function(){
17 | [[$.Number(1), 1],
18 | [$.String("10"), 10],
19 | [$.Boolean(false), 0]].forEach(function(x){
20 | expect.run(
21 | $.Program(
22 | $.Expression(
23 | $.Call(Number, [x[0]]))))
24 |
25 | .testResult()
26 | .type('number', x[1]);
27 | });
28 | }],
29 | ["new Number() unboxes to zero.",
30 | function(){
31 | expect.run(
32 | $.Program(
33 | $.Expression(
34 | $.Add($.New(Number, []), $.Number(100)))))
35 |
36 | .testResult()
37 | .type('number', 100);
38 |
39 | expect.run(
40 | $.Program(
41 | $.Expression(
42 | $.Add($.New(Number, []), $.String('abc')))))
43 |
44 | .testResult()
45 | .type('string', "0abc");
46 | }],
47 | ["Set on number",
48 | function(){
49 | expect.run(
50 | $.Program(
51 | $.Expression(
52 | $.Assign(a, $.New(Number, []))),
53 | $.Expression(
54 | $.Assign($.Member(a, b), $.Number(10)))))
55 | .test($.Expression($.Add(a, $.Member(a, b))))
56 | .type('number', 10);
57 | }],
58 | ["`Number.prototype.valueOf`",
59 | function(){
60 | expect.run(
61 | $.Program(
62 | $.Expression(
63 | $.Assign(a, $.New(Number, [$.Number(3)]))),
64 | $.Expression(
65 | $.Assign(b, $.Number(10)))))
66 |
67 | .test($.Expression($.Call($.Member(a, $.Id('valueOf')), [])))
68 | .type('number', 3)
69 |
70 | .test(
71 | $.Expression(
72 | $.Call(
73 | $.Member($.Member($.Member(Number, $.Id('prototype')), $.Id('valueOf')), $.Id('call')),
74 | [b])))
75 | .type('number', 10);
76 | }],
77 | ]
78 | };
79 | });
80 |
--------------------------------------------------------------------------------
/test/builtin/testString.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | var String = $.Id('String');
11 |
12 | return {
13 | 'module': "Builtin String",
14 | 'tests': [
15 | ["String(x) converts to string",
16 | function(){
17 | [[$.String('abc'), 'abc'],
18 | [$.Number(10), '10'],
19 | [$.Boolean(false), 'false'],
20 | [$.Object(), '[object Object]']].forEach(function(x){
21 | expect.run(
22 | $.Program(
23 | $.Expression(
24 | $.Call(String, [x[0]]))))
25 |
26 | .testResult()
27 | .type('string', x[1]);
28 | });
29 | }],
30 | ["new String() unboxes to empty string.",
31 | function(){
32 | expect.run(
33 | $.Program(
34 | $.Expression(
35 | $.Add($.New(String, []), $.String('abc')))))
36 |
37 | .testResult()
38 | .type('string', 'abc');
39 | }],
40 | ["Set on String",
41 | function(){
42 | expect.run(
43 | $.Program(
44 | $.Expression(
45 | $.Assign(a, $.New(String, [$.String('abc')]))),
46 | $.Expression(
47 | $.Assign($.Member(a, b), $.String('xyz')))))
48 |
49 | .test($.Expression($.Add(a, $.Member(a, b))))
50 | .type('string', 'abcxyz');
51 | }],
52 | ["`String.prototype.valueOf`",
53 | function(){
54 | expect.run(
55 | $.Program(
56 | $.Expression(
57 | $.Assign(a, $.New(String, [$.String('abc')]))),
58 | $.Expression(
59 | $.Assign(b, $.String('xyz')))))
60 |
61 | .test($.Expression($.Call($.Member(a, $.Id('valueOf')), [])))
62 | .type('string','abc')
63 |
64 | .test(
65 | $.Expression(
66 | $.Call(
67 | $.Member($.Member($.Member(String, $.Id('prototype')), $.Id('valueOf')), $.Id('call')),
68 | [b])))
69 | .type('string', 'xyz');
70 | }],
71 | ]
72 | };
73 | });
74 |
--------------------------------------------------------------------------------
/test/expect.js:
--------------------------------------------------------------------------------
1 | define(['atum/compute',
2 | 'atum/compute/context',
3 | 'atum/interpret',
4 | 'atum/semantics/semantics',
5 | 'atum/builtin/impl/global',
6 | 'atum/builtin/operations/global'],
7 | function(compute,
8 | context,
9 | interpret,
10 | semantics,
11 | global,
12 | global_ops){
13 | //"use strict";
14 |
15 | var Context = function(parent, value, ctx) {
16 | this.parent = parent;
17 | this.value = value;
18 | this.ctx = ctx;
19 | };
20 |
21 | Context.prototype.equal = function(f, expected, msg) {
22 | assert.equal(f(this.value), expected, msg);
23 | return this;
24 | };
25 |
26 | Context.prototype.type = function(t, v) {
27 | if (arguments.length > 1) {
28 | return this
29 | .equal(function(x) { return x.type; }, t)
30 | .equal(function(x) { return x.value; }, v);
31 | }
32 | return this
33 | .equal(function(x) { return x.type; }, t);
34 | };
35 |
36 | Context.prototype.test = function(/*...*/) {
37 | return this.parent.test.apply(this.parent, arguments);
38 | };
39 |
40 | Context.prototype.testResult = function(/*...*/) {
41 | return this.parent.testResult.apply(this.parent, arguments);
42 | };
43 |
44 | var Result = function(isError, value, ctx) {
45 | this.error = isError;
46 | this.value = value;
47 | this.ctx = ctx;
48 | };
49 |
50 | Result.prototype.run = function(node) {
51 | return interpret.exec(
52 | semantics.mapSemantics(node),
53 | this.ctx,
54 | function(x, ctx){ return new Result(false, x, ctx); },
55 | function(x, ctx){ return new Result(true, x, ctx); });
56 | };
57 |
58 | Result.prototype.equal = function(expr, expected, msg) {
59 | assert.equal(this.run(expr).value, expected, msg);
60 | return this;
61 | };
62 |
63 | Result.prototype.test = function(expr) {
64 | return new Context(this, this.run(expr).value.value);
65 | };
66 |
67 | Result.prototype.testResult = function() {
68 | return new Context(this, this.value);
69 | };
70 |
71 | Result.prototype.type = function(expr, t, v) {
72 | type(t, v)(this.run(expr).value.value);
73 | return this;
74 | };
75 |
76 | Result.prototype.isError = function() {
77 | assert.ok(this.error);
78 | return this;
79 | };
80 |
81 | //console.profile();
82 |
83 | var globalCtx = interpret.exec(
84 | compute.sequence(
85 | global.initialize(),
86 | global_ops.enterGlobal(),
87 | compute.computeContext),
88 | context.ComputeContext.empty,
89 | function(x) { return x; },
90 | function(x) { return x; });
91 |
92 | //console.profileEnd();
93 |
94 | var run = function(root) {
95 | return interpret.exec(
96 | semantics.programBody(semantics.sourceElements(root.body)),
97 | globalCtx,
98 | function(x, ctx){ return new Result(false, x, ctx); },
99 | function(x, ctx){ return new Result(true, x, ctx); });
100 | };
101 |
102 |
103 | var type = function(t, v) {
104 | return (arguments.length > 1 ?
105 | function(result) {
106 | assert.equal(result.type, t);
107 | assert.equal(result.value, v);
108 | } :
109 | function(result) {
110 | assert.equal(result.type, t);
111 | });
112 | };
113 |
114 | return {
115 | 'Result': Result,
116 |
117 | 'run': run,
118 |
119 | 'type': type,
120 | };
121 |
122 | });
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Atum Tests
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/test/testIn.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c'),
9 | Object = $.Id('Object'),
10 | defineProperty = $.Member(Object, $.Id('defineProperty'));
11 |
12 | return {
13 | 'module': "In operator",
14 | 'tests': [
15 | ["Simple In ",
16 | function(){
17 | expect.run(
18 | $.Program(
19 | $.Expression(
20 | $.Assign(a, $.Object(
21 | $.ObjectValue($.String('b'), $.Number(1)))))))
22 |
23 | .test($.Expression($.In($.String('b'), a)))
24 | .type('boolean', true)
25 |
26 | .test($.Expression($.In($.String('c'), a)))
27 | .type('boolean', false);
28 | }],
29 | ["In expression lhs type conversion",
30 | function(){
31 | expect.run(
32 | $.Program(
33 | $.Expression(
34 | $.Assign(a, $.Array(
35 | $.Number(14),
36 | $.Number(16))))))
37 |
38 | .test($.Expression($.In($.Number(1), a)))
39 | .type('boolean', true)
40 |
41 | .test($.Expression($.In($.Add($.Number(0), $.Number(1)), a)))
42 | .type('boolean', true)
43 |
44 | .test($.Expression($.In($.Add($.Number(5), $.Number(1)), a)))
45 | .type('boolean', false);
46 | }],
47 | ["In inherited",
48 | function(){
49 | expect.run(
50 | $.Program(
51 | $.Expression(
52 | $.Assign(a, $.Object()))))
53 |
54 | .test($.Expression($.In($.String('toString'), a)))
55 | .type('boolean', true);
56 | }],
57 |
58 | ["In non enumerable",
59 | function(){
60 | expect.run(
61 | $.Program(
62 | $.Expression(
63 | $.Assign(a, $.Call(defineProperty, [
64 | $.Object(),
65 | $.String('b'),
66 | $.Object(
67 | $.ObjectValue($.String('value'), $.Number(10)),
68 | $.ObjectValue($.String('enumerable'), $.Number(false)))]
69 | )))))
70 |
71 | .test($.Expression($.In($.String('b'), a)))
72 | .type('boolean', true);
73 | }],
74 | ["In undefined",
75 | function(){
76 | expect.run(
77 | $.Program(
78 | $.Expression(
79 | $.Assign(a, $.Call(defineProperty, [
80 | $.Object(),
81 | $.String('b'),
82 | $.Object()])))))
83 |
84 | .test($.Expression($.In($.String('b'), a)))
85 | .type('boolean', true);
86 | }],
87 | ]
88 | };
89 | });
90 |
--------------------------------------------------------------------------------
/test/testInstanceof.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c'),
9 | Object = $.Id('Object'),
10 | Number = $.Id('Number'),
11 | defineProperty = $.Member(Object, $.Id('defineProperty')),
12 | create = $.Member(Object, $.Id('create'));
13 |
14 | return {
15 | 'module': "Instanceof operator",
16 | 'tests': [
17 | ["Simple Instanceof",
18 | function(){
19 | expect.run(
20 | $.Program(
21 | $.Expression(
22 | $.Assign(a, $.Object()))))
23 |
24 | .test($.Expression($.Instanceof(a, Object)))
25 | .type('boolean', true)
26 |
27 | .test($.Expression($.Instanceof(a, Number)))
28 | .type('boolean', false);
29 | }],
30 | ["Inherited",
31 | function(){
32 | expect.run(
33 | $.Program(
34 | $.FunctionDeclaration(a, [], $.Block()),
35 | $.FunctionDeclaration(b, [], $.Block()),
36 | $.Expression(
37 | $.Assign($.Member(b, $.Id('prototype')), $.New(a, []))),
38 | $.Expression(
39 | $.Assign(c,
40 | $.New(b, [])))))
41 |
42 | .test($.Expression($.Instanceof(b, a)))
43 | .type('boolean', false)
44 |
45 | .test($.Expression($.Instanceof(c, Object)))
46 | .type('boolean', true)
47 |
48 | .test($.Expression($.Instanceof(c, a)))
49 | .type('boolean', true)
50 |
51 | .test($.Expression($.Instanceof(c, b)))
52 | .type('boolean', true);
53 | }],
54 | ["Builtin",
55 | function(){
56 | expect.run(
57 | $.Program())
58 |
59 | .test($.Expression($.Instanceof(Number, Number)))
60 | .type('boolean', false)
61 |
62 | .test($.Expression($.Instanceof($.Number(5), Number)))
63 | .type('boolean', false)
64 |
65 | .test($.Expression($.Instanceof($.New(Number, []), Number)))
66 | .type('boolean', true);
67 | }],
68 | ]
69 | };
70 | });
71 |
--------------------------------------------------------------------------------
/test/testLogical.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | return {
11 | 'module': "Logical Expressions",
12 | 'tests': [
13 | // Logical And
14 | ["Logical And short",
15 | function(){
16 | expect.run(
17 | $.Program(
18 | $.Var(
19 | $.Declarator(a, $.Number(0)),
20 | $.Declarator(b, $.Number(10))),
21 | $.Expression(
22 | $.LogicalAnd($.PostIncrement(a), $.PostIncrement(b)))))
23 | .testResult()
24 | .type('number', 0)
25 | .test($.Expression(a))
26 | .type('number', 1);
27 | }],
28 | ["Logical And no short",
29 | function(){
30 | expect.run(
31 | $.Program(
32 | $.Var(
33 | $.Declarator(a, $.Number(0)),
34 | $.Declarator(b, $.Number(10))),
35 | $.Expression(
36 | $.LogicalAnd($.PreIncrement(a), $.PostIncrement(b)))))
37 | .testResult()
38 | .type('number', 10);
39 | }],
40 | // Logical Or
41 | ["Logical Or short",
42 | function(){
43 | expect.run(
44 | $.Program(
45 | $.Var(
46 | $.Declarator(a, $.Number(0)),
47 | $.Declarator(b, $.Number(10))),
48 | $.Expression(
49 | $.LogicalOr($.PostIncrement(a), $.PostIncrement(b)))))
50 | .testResult()
51 | .type('number', 10)
52 | .test($.Expression(a))
53 | .type('number', 1)
54 | .test($.Expression(b))
55 | .type('number', 11);
56 | }],
57 | ["Logical Or no short",
58 | function(){
59 | expect.run(
60 | $.Program(
61 | $.Var(
62 | $.Declarator(a, $.Number(0)),
63 | $.Declarator(b, $.Number(10))),
64 | $.Expression(
65 | $.LogicalOr($.PreIncrement(a), $.PostIncrement(b)))))
66 | .testResult()
67 | .type('number', 1)
68 | .test($.Expression(a))
69 | .type('number', 1)
70 | .test($.Expression(b))
71 | .type('number', 10);
72 | }],
73 | ],
74 | };
75 | });
76 |
--------------------------------------------------------------------------------
/test/testNumber.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | return {
7 | 'module': "Number",
8 | 'tests': [
9 | ["Number Literal",
10 | function(){
11 | ([10, -10, 1e6, -1e6, 1.5, -1.5]).forEach(function(x) {
12 | expect.run(
13 | $.Program(
14 | $.Expression($.Number(x))))
15 | .testResult()
16 | .type('number', x);
17 | });
18 | }],
19 | ["Binary Plus Number",
20 | function(){
21 | ([10, -10, 1e6, -1e6, 1.5, -1.5]).forEach(function(x) {
22 | expect.run(
23 | $.Program(
24 | $.Expression($.Add($.Number(x), $.Number(10)))))
25 |
26 | .testResult()
27 | .type('number', x + 10);
28 | });
29 | }],
30 | ["String->Number",
31 | function(){
32 | ([["3.3e10", 3.3e10], [" 10 ", 10]]).forEach(function(x) {
33 | expect.run(
34 | $.Program(
35 | $.Expression($.Plus($.String(x[0])))))
36 |
37 | .testResult()
38 | .type('number', x[1]);
39 | });
40 | }],
41 |
42 | ],
43 | };
44 | });
45 |
--------------------------------------------------------------------------------
/test/testString.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | return {
7 | 'module': "String",
8 | 'tests': [
9 | ["String Literal",
10 | function(){
11 | (["", "abc", '""', "''", "a\nb", "e\u0041ab"]).forEach(function(x) {
12 | expect.run(
13 | $.Program(
14 | $.Expression($.String(x))))
15 |
16 | .testResult()
17 | .type('string', x);
18 | });
19 | }],
20 | ["Binary Plus String, Both Sides",
21 | function(){
22 | ([['', 'abc'], ['abc', ''], ['ab', 'c']]).forEach(function(x) {
23 | expect.run(
24 | $.Program(
25 | $.Expression(
26 | $.Add(
27 | $.String(x[0]),
28 | $.String(x[1])))))
29 |
30 | .testResult()
31 | .type('string', x[0] + x[1]);
32 | });
33 | }],
34 | ["Binary Plus String Force String Conversion",
35 | function(){
36 | expect.run($.Program())
37 |
38 | .test($.Expression($.Add($.Number(10), $.String("abc"))))
39 | .type('string', '10abc')
40 |
41 | .test($.Expression($.Add($.String("abc"), $.Number(10))))
42 | .type('string', 'abc10');
43 | }],
44 | ],
45 | };
46 | });
47 |
--------------------------------------------------------------------------------
/test/testUnary.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | return {
11 | 'module': "Unary Tests",
12 | 'tests': [
13 | // void
14 | ["Void",
15 | function(){
16 | expect.run(
17 | $.Program(
18 | $.Expression($.Void($.Number(10)))))
19 |
20 | .testResult()
21 | .type('undefined', undefined);
22 | }],
23 | ["Void Side Effects",
24 | function(){
25 | expect.run(
26 | $.Program(
27 | $.Expression($.Sequence(
28 | $.Assign(a, $.Number(0)),
29 | $.Void($.PreIncrement(a)),
30 | a))))
31 |
32 | .testResult()
33 | .type('number', 1);
34 | }],
35 | // Unary plus
36 | ["Unary Plus Number",
37 | function(){
38 | ([10, -10, 1e6, -1e6, 1.5, -1.5])
39 | .forEach(function(x) {
40 | expect.run(
41 | $.Program(
42 | $.Expression($.Plus($.Number(x)))))
43 |
44 | .testResult()
45 | .type('number', x);
46 | });
47 | }],
48 | // Unary Minus
49 | ["Unary Minus Number",
50 | function(){
51 | ([10, -10, 1e6, -1e6, 1.5, -1.5])
52 | .forEach(function(x) {
53 | expect.run(
54 | $.Program(
55 | $.Expression($.Negate($.Number(x)))))
56 |
57 | .testResult()
58 | .type('number', -x);
59 |
60 | });
61 | }],
62 |
63 | // Logical Not
64 | ["Logical Not Boolean",
65 | function(){
66 | ([true, false])
67 | .forEach(function(x) {
68 | expect.run(
69 | $.Program(
70 | $.Expression($.LogicalNot($.Boolean(x)))))
71 |
72 | .testResult()
73 | .type('boolean', !x);
74 | });
75 | }],
76 |
77 | // Bitwise Not
78 | ["Bitwise Not",
79 | function(){
80 | ([$.Number(1),
81 | $.Number(1.5),
82 | $.Number(-1),
83 | $.String("1")])
84 | .forEach(function(x) {
85 | expect.run(
86 | $.Program(
87 | $.Expression($.BitwiseNot(x))))
88 |
89 | .testResult()
90 | .type('number', ~x.value);
91 | });
92 | }],
93 |
94 | // Typeof
95 | ["Typeof string",
96 | function(){
97 | expect.run(
98 | $.Program(
99 | $.Expression($.Typeof($.String("")))))
100 |
101 | .testResult()
102 | .type('string', 'string');
103 | }],
104 | ],
105 | };
106 | });
107 |
--------------------------------------------------------------------------------
/test/testWith.js:
--------------------------------------------------------------------------------
1 | define(['$',
2 | 'expect'],
3 | function($,
4 | expect){
5 |
6 | var a = $.Id('a'),
7 | b = $.Id('b'),
8 | c = $.Id('c');
9 |
10 | return {
11 | 'module': "With",
12 | 'tests': [
13 | ["Simple With",
14 | function(){
15 | expect.run(
16 | $.Program(
17 | $.Expression($.Assign(a,
18 | $.Object(
19 | $.ObjectValue($.String('b'), $.Number(1))))),
20 | $.With(a, $.Block(
21 | $.Expression(b)))))
22 |
23 | .testResult()
24 | .type('number', 1);
25 | }],
26 | ["Simple global this",
27 | function(){
28 | expect.run(
29 | $.Program(
30 | $.Expression($.Assign(a, $.Number(1))),
31 | $.With($.This(), $.Block(
32 | $.Expression(a)))))
33 |
34 | .testResult()
35 | .type('number', 1);
36 | }],
37 | ["Delete",
38 | function(){
39 | expect.run(
40 | $.Program(
41 | $.Expression($.Assign(a,
42 | $.Object(
43 | $.ObjectValue($.String('b'), $.Number(1))))),
44 | $.With(a, $.Block(
45 | $.Expression($.Delete(b))))))
46 |
47 | .testResult()
48 | .type('boolean', true)
49 |
50 | .test($.Expression($.Member(a, b)))
51 | .type('undefined', undefined);
52 | }],
53 | ]
54 | };
55 | });
56 |
--------------------------------------------------------------------------------