├── .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 |
116 | 117 |
118 |
119 |
120 |
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 | --------------------------------------------------------------------------------