Updated documentation for new Netscript. Added new polyfills for new JS interpreter

This commit is contained in:
danielyxie 2018-07-24 13:29:38 -05:00
parent a39dda019e
commit ab287b7c44
10 changed files with 248 additions and 184 deletions

File diff suppressed because one or more lines are too long

@ -14,10 +14,9 @@ to reach out to the developer!
:maxdepth: 5 :maxdepth: 5
:caption: Sections: :caption: Sections:
Learn to Program <netscriptlearntoprogram>
Netscript 1.0 <netscript1>
NetscriptJS (Netscript 2.0) <netscriptjs> NetscriptJS (Netscript 2.0) <netscriptjs>
Data Types and Variables <netscriptdatatypes>
Operators <netscriptoperators>
Loops and Conditionals <netscriptloopsandconditionals>
Script Arguments <netscriptscriptarguments> Script Arguments <netscriptscriptarguments>
Basic Functions <netscriptfunctions> Basic Functions <netscriptfunctions>
Advanced Functions <netscriptadvancedfunctions> Advanced Functions <netscriptadvancedfunctions>

32
doc/source/netscript1.rst Normal file

@ -0,0 +1,32 @@
.. _netscript1:
Netscript 1.0
=============
Netscript 1.0 is implemented using modified version of Neil Fraser's
`JS-Interpreter <https://github.com/NeilFraser/JS-Interpreter>`_.
This interpreter was created for ES5, which means that the code written
for Netscript 1.0 must be compliant for that version. However, some additional
ES6+ features are implemented through polyfills.
Netscript 1.0 scripts end with the ".script" extension.
Which ES6+ features are supported?
----------------------------------
Netscript 1.0 is a ES5 interpreter, but the following features from versions ES6 and
above are supported as well.
If there is an additional ES6+ feature you would like to see implemented with a polyfill,
feel free to `open an issue <https://github.com/danielyxie/bitburner/issues>`_ (and provide
the polyfill if possible).
* import - See :ref:`netscriptimporting`
* `Array <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array>`_
* `find() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find>`_
* `findIndex() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex>`_
* `includes() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes>`_
* `String <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String>`_
* `endsWith() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith>`_
* `includes() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes>`_
* `startsWith() <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith>`_

@ -1,44 +0,0 @@
Netscript Data Types and Variables
==================================
Data Types
----------
Netscript supports three primitive data types:
**Numbers** - Positive numerics, such as integers and floats. Examples: 6, 0, 10.5
**Strings** - A sequence of characters that represents text. The characters must be encapsulated by single or
double quotes. Example: "This is a string" or equivalently 'This is a string'.
*Strings are fully functional* `Javascript strings <https://www.w3schools.com/jsref/jsref_obj_string.asp>`_,
*which means that all of the member functions of Javascript strings such as toLowerCase() and includes() are also available in Netscript!*
**Boolean** - true or false
**Array** - An array is a special container object that is capable of holding many different values. Arrays are simply Javascript
arrays, and most Javascript array methods can be used in Netscript as well (join(), pop(), splice(), etc.). You can read more about
`Javascript arrays here <https://www.w3schools.com/js/js_arrays.asp>`_
Variables
---------
Variables can be thought of as named containers. Their purpose is to label and store data. The data stored in the
variable can then be accessed and changed by referring to the variable's name. The name of a variable must start with
either a letter or an underscore. The rest of the variable name can contain any alphanumeric (letters and numbers),
as well as hyphens and underscores.
The Netscript language is untyped, meaning that any variable can hold any of the data types above. The value type of a variable
can also change. For example, if a variable initially holds a number, it can later hold a string.
The following shows how you can declare and initialize variables::
i = 1;
s = "This is a string";
b = false;
After declaring a variable, the values in variables can be used simply by referencing the name. For example::
j = i + 5;
s2 = s + " Adding more letters onto the string"
The first command above will store the value 6 in the variable j. The second command will store the string "This is a string Adding more letters onto the string" into the variable s2.

@ -8,7 +8,7 @@ still being able to access the Netscript functions.
NetscriptJS was developed primarily by `Github user jaguilar <https://github.com/jaguilar>`_ NetscriptJS was developed primarily by `Github user jaguilar <https://github.com/jaguilar>`_
On top of having almost all of the features and capabilities of Javascript, NetscriptJS is also On top of having almost all of the features and capabilities of JavaScript, NetscriptJS is also
significantly faster than Netscript 1.0. significantly faster than Netscript 1.0.
This documentation will not go over any of the additional features of NetscriptJS, since This documentation will not go over any of the additional features of NetscriptJS, since

@ -0,0 +1,70 @@
.. _netscriptlearntoprogram:
Learn to Program in Netscript
=============================
Netscript is simply a subset of
`JavaScript <https://developer.mozilla.org/en-US/docs/Web/JavaScript>`_,
with some additional functions added in to allow interaction with the game.
For Beginner Programmers
------------------------
If you have little to no programming experience, that's okay! You don't need to be
a great programmer in order to enjoy or play this game. In fact, this game could
help you learn some basic programming concepts.
Here are some good tutorials for learning programming/JavaScript as a beginner:
* `Learn-JS <http://www.learn-js.org/en/Welcome>`_
* `Speaking JavaScript <http://speakingjs.com/es5/index.html>`_
This is a bit on the longer side. You can skip all of the historical
background stuff. Recommended chapters: 1, 7-18
For Experienced Programmers
---------------------------
The following section lists several good tutorials/resources for those who have experience
programming but who have not worked extensively with JavaScript before.
Before that, however, it's important to clarify some terminology about the different
versions of JavaScript. These are summarized in this article:
`WTF is ES6, ES8, ES2017, ECMAScript... <https://codeburst.io/javascript-wtf-is-es6-es8-es-2017-ecmascript-dca859e4821c>`_
An important takeaway from this article is that ES6, also known as ES2015, introduced
many major features that are commonly seen in modern JavaScript programming. However, this
means that ES5 engines and interpreters will fail if they encounters these ES6 features. You'll see why this
is important further down.
* `MDN Introduction to JS <https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript>`_
* `Eloquent JavaScript (ES6+) <http://eloquentjavascript.net/>`_
Recommended Chapters: Introduction, 1-6
* `Modern Javascript Tutorial (ES6+) <https://javascript.info/>`_
Recommended Chapters: 2, 4-6
Netscript 1.0 vs Netscript 2.0
------------------------------
There are two versions of Netscript:
* :doc:`netscript1`
* :doc:`netscriptjs`
Visit the pages above to get more details about each version. If you are new
to programming or unfamiliar with JavaScript, I would recommend starting out
with :doc:`netscript1`. Experienced web developers can use :doc:`netscriptjs`
to take advantage of faster speeds and additional features.
Here is a short summary of the differences between Netscript 1.0 and Netscript 2.0:
**Netscript 1.0**
* ES5
* Some ES6 features implemented with polyfills
* Slow compared to NetscriptJS (interpreter runs at the "Netscript Exec Time" speed configured in options)
* Compatible with all browsers
**Netscript JS (Netscript 2.0)**
* Supports (almost) all features of modern JavaScript
* Extremely fast - code is executed as an Async Function
* Currently only works with Google Chrome browser
* Each script becomes a module and therefore all instances of that script can easily
share data between each other (essentially global/static variables)

@ -1,39 +0,0 @@
Netscript Loops and Conditionals
================================
Netscript loops and conditionals are the same as Javascript. However, the one caveat is that when declaring variables such as the
iterator for traversing a loop, you should not use the 'var' or 'let' keyword. For reference, you can see the Javascript
documentation for loops/conditionals here:
`While loops <https://www.w3schools.com/js/js_loop_while.asp>`_
`For loops <https://www.w3schools.com/js/js_loop_for.asp>`_
`Conditionals (If/Else statements) <https://www.w3schools.com/js/js_if_else.asp>`_
Here are some simple code examples that show the use of loops and conditionals in Netscript.
The following is a while loop that runs the hack() Netscript function ten times::
i = 0;
while (i < 10) {
hack('foodnstuff');
i = i + 1;
}
The following is a for loop that runs the hack() Netscript function ten times::
for (i = 0; i < 10; ++i) {
hack("foodnstuff");
}
The following is a conditional that uses the getServerMoneyAvailable() Netscript function to check how much money
exists on the 'foodnstuff' server. If there is more than $200,000 on the server, then the server will be hacked.
Otherwise, the money available on the server will be grown using the grow() Netscript function::
if (getServerMoneyAvailable('foodnstuff') > 200000) {
hack("foodnstuff");
} else {
grow("foodnstuff");
}

@ -142,6 +142,8 @@ Comments are not evaluated as code, and can be used to document and/or explain c
* comment */ * comment */
print("This code will actually get executed"); print("This code will actually get executed");
.. _netscriptimporting:
Importing Functions Importing Functions
------------------- -------------------

@ -1,53 +0,0 @@
Netscript Operators
===================
Operators
---------
Binary Operators
^^^^^^^^^^^^^^^^
Binary operators require two operands and produce a result based on their values. In general, binary
operators do not change the value of the operands.
=========== =========================== ==============================================================
Operator Name Example/Comments
=========== =========================== ==============================================================
= Assignment i = 5 would assign the value 5 to the variable i
\+ Addition 5 + 12 would return 17
\- Subtraction 20 - 8 would return 12
\* Multiplication 4 * 5 would return 20
\/ Division 50 / 10 would return 5
% Modulo 50 % 9 would return 5
&& Logical AND true && false would return false
|| Logical OR true || false would return true
< Less than 4 < 5 would return true
> Greater than 4 > 5 would return false
<= Less than or equal to 5 <= 5 would return true
>= Greater than or equal to 5 >= 4 would return true
== Equality 1 == 1 would return true
!= Inequality 4 != 5 would return true
=== Strict equality 1 === "1" would return false
!== Strict inequality 1 !== "1" would return true
=========== =========================== ==============================================================
Unary Operators
^^^^^^^^^^^^^^^
Unary operators require only a single operand and produce a result based on their values. Some unary operators will
change the value of their operands. For example::
i = 0;
++i;
Running the pre-increment unary operator (++) in the code above changes the value of the variable i.
=============== =========================== ==============================================================================================
Operator Name Example/comments
=============== =========================== ==============================================================================================
! Logical NOT operator !true would return false, and !false would return true. Does not change operand's value
\- Negation Negates a number. Only works for numerics. Does not change operand's value
++ Pre-increment ++i or i++. WARNING: This only pre-increments, even if you put i++. Changes operand's value
-- Pre-decrement --i or i--. WARNING: This only pre-decrements, even if you put i--. Changes operand's value
=============== =========================== ==============================================================================================

@ -910,6 +910,66 @@ Interpreter.prototype.initArray = function(scope) {
"}", "}",
"});", "});",
// Polyfill copied from:
// https://tc39.github.io/ecma262/#sec-array.prototype.find
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
"if (!Array.prototype.find) {",
"Object.defineProperty(Array.prototype, 'find', {",
"value: function(predicate) {",
"if (this == null) {",
"throw new TypeError('\"this\" is null or not defined');",
"}",
"var o = Object(this);",
"var len = o.length >>> 0;",
"if (typeof predicate !== 'function') {",
"throw new TypeError('predicate must be a function');",
"}",
"var thisArg = arguments[1];",
"var k = 0;",
"while (k < len) {",
"var kValue = o[k];",
"if (predicate.call(thisArg, kValue, k, o)) {",
"return kValue;",
"}",
"k++;",
"}",
"return undefined;",
"},",
"configurable: true,",
"writable: true",
"});",
"}",
// Poly fill copied from:
// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
"if (!Array.prototype.findIndex) {",
"Object.defineProperty(Array.prototype, 'findIndex', {",
"value: function(predicate) {",
"if (this == null) {",
"throw new TypeError('\"this\" is null or not defined');",
"}",
"var o = Object(this);",
"var len = o.length >>> 0;",
"if (typeof predicate !== 'function') {",
"throw new TypeError('predicate must be a function');",
"}",
"var thisArg = arguments[1];",
"var k = 0;",
"while (k < len) {",
"var kValue = o[k];",
"if (predicate.call(thisArg, kValue, k, o)) {",
"return k;",
"}",
"k++;",
"}",
"return -1;",
"},",
"configurable: true,",
"writable: true",
"});",
"}",
// Polyfill copied from: // Polyfill copied from:
// developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach // developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
"Object.defineProperty(Array.prototype, 'forEach',", "Object.defineProperty(Array.prototype, 'forEach',",
@ -928,6 +988,48 @@ Interpreter.prototype.initArray = function(scope) {
"}", "}",
"});", "});",
// Polyfill copied from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
"Object.defineProperty(Array.prototype, 'includes', {",
"value: function(searchElement, fromIndex) {",
"if (this == null) {",
"throw new TypeError('\"this\" is null or not defined');",
"}",
"// 1. Let O be ? ToObject(this value).",
"var o = Object(this);",
"// 2. Let len be ? ToLength(? Get(O, \"length\")).",
"var len = o.length >>> 0;",
"// 3. If len is 0, return false.",
"if (len === 0) {",
"return false;",
"}",
"// 4. Let n be ? ToInteger(fromIndex).",
"// (If fromIndex is undefined, this step produces the value 0.)",
"var n = fromIndex | 0;",
"// 5. If n ≥ 0, then",
"// a. Let k be n.",
"// 6. Else n < 0,",
"// a. Let k be len + n.",
"// b. If k < 0, let k be 0.",
"var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);",
"function sameValueZero(x, y) {",
"return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));",
"}",
"// 7. Repeat, while k < len",
"while (k < len) {",
"// a. Let elementK be the result of ? Get(O, ! ToString(k)).",
"// b. If SameValueZero(searchElement, elementK) is true, return true.",
"if (sameValueZero(o[k], searchElement)) {",
"return true;",
"}",
"// c. Increase k by 1. ",
"k++;",
"}",
"// 8. Return false",
"return false;",
"}",
"});",
// Polyfill copied from: // Polyfill copied from:
// developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map // developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map
"Object.defineProperty(Array.prototype, 'map',", "Object.defineProperty(Array.prototype, 'map',",
@ -1012,48 +1114,6 @@ Interpreter.prototype.initArray = function(scope) {
"}", "}",
"});", "});",
// Polyfill copied from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
"Object.defineProperty(Array.prototype, 'includes', {",
"value: function(searchElement, fromIndex) {",
"if (this == null) {",
"throw new TypeError('\"this\" is null or not defined');",
"}",
"// 1. Let O be ? ToObject(this value).",
"var o = Object(this);",
"// 2. Let len be ? ToLength(? Get(O, \"length\")).",
"var len = o.length >>> 0;",
"// 3. If len is 0, return false.",
"if (len === 0) {",
"return false;",
"}",
"// 4. Let n be ? ToInteger(fromIndex).",
"// (If fromIndex is undefined, this step produces the value 0.)",
"var n = fromIndex | 0;",
"// 5. If n ≥ 0, then",
"// a. Let k be n.",
"// 6. Else n < 0,",
"// a. Let k be len + n.",
"// b. If k < 0, let k be 0.",
"var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);",
"function sameValueZero(x, y) {",
"return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));",
"}",
"// 7. Repeat, while k < len",
"while (k < len) {",
"// a. Let elementK be the result of ? Get(O, ! ToString(k)).",
"// b. If SameValueZero(searchElement, elementK) is true, return true.",
"if (sameValueZero(o[k], searchElement)) {",
"return true;",
"}",
"// c. Increase k by 1. ",
"k++;",
"}",
"// 8. Return false",
"return false;",
"}",
"});",
"(function() {", "(function() {",
"var sort_ = Array.prototype.sort;", "var sort_ = Array.prototype.sort;",
"Array.prototype.sort = function(opt_comp) {", "Array.prototype.sort = function(opt_comp) {",
@ -1203,6 +1263,43 @@ Interpreter.prototype.initString = function(scope) {
"return str;", "return str;",
"};", "};",
"})();", "})();",
// Polyfill copied from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
"if (!String.prototype.endsWith) {",
"String.prototype.endsWith = function(search, this_len) {",
"if (this_len === undefined || this_len > this.length) {",
"this_len = this.length;",
"}",
"return this.substring(this_len - search.length, this_len) === search;",
"};",
"}",
//Polyfill copied from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
"if (!String.prototype.includes) {",
"String.prototype.includes = function(search, start) {",
"'use strict';",
"if (typeof start !== 'number') {",
"start = 0;",
"}",
" ",
"if (start + search.length > this.length) {",
"return false;",
"} else {",
"return this.indexOf(search, start) !== -1;",
"}",
"};",
"}",
// Polyfill copied from:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
"if (!String.prototype.startsWith) {",
"String.prototype.startsWith = function(search, pos) {",
"return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;",
"};",
"}",
""); "");
}; };