{"id":15069874,"url":"https://github.com/ronenness/adder","last_synced_at":"2025-04-10T17:05:27.171Z","repository":{"id":57098208,"uuid":"70284623","full_name":"RonenNess/adder","owner":"RonenNess","description":"Executing untrusted code with ease.","archived":false,"fork":false,"pushed_at":"2018-11-03T13:39:46.000Z","size":1825,"stargazers_count":48,"open_issues_count":2,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-08T01:55:37.596Z","etag":null,"topics":["eval","javascript","javascript-library","javascript-sandbox","node-js","nodejs","scripting-language"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RonenNess.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-07T21:34:45.000Z","updated_at":"2025-04-04T10:02:00.000Z","dependencies_parsed_at":"2022-08-20T16:51:04.481Z","dependency_job_id":null,"html_url":"https://github.com/RonenNess/adder","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RonenNess%2Fadder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RonenNess%2Fadder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RonenNess%2Fadder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RonenNess%2Fadder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RonenNess","download_url":"https://codeload.github.com/RonenNess/adder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248260231,"owners_count":21074207,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eval","javascript","javascript-library","javascript-sandbox","node-js","nodejs","scripting-language"],"created_at":"2024-09-25T01:45:17.005Z","updated_at":"2025-04-10T17:05:27.136Z","avatar_url":"https://github.com/RonenNess.png","language":"JavaScript","readme":"![AdderScript](img/logo-sm.png \"AdderScript\")\n\n- [Official Site](http://adderscript.com/)\n\n- [Official Docs](http://adderscript.com/docs.html)\n\n- [Online Sandbox](http://adderscript.com/examples/sandbox.html)\n\n# AdderScript\n\nExecuting untrusted code with ease.\n\n## What is it\n\nAdder is a lightweight python-like language, implemented on top of JavaScript and designed to be safe to execute untrusted code.\n\n### Why?\n\nThe main purpose of Adder is to let you execute untrusted code on other users's browsers and even on your Node.js server, without worrying about security complications.\n\nAdder will not let the untrusted code access anything you don't want it to access, will not allow it to get stuck or hog resources, and will make sure it can't do any harm or go outside its boundaries.\n\nThe main reason Adder is secured is that *no JavaScript code is ever executed using plain eval()*.\nInstead, everything is parsed and interpreted by the Adder interpreter, that is built and designed to be limited and safe.\n\n## Advantages\n\nHere are the key features of Adder:\n\n- Beautiful Pythonic syntax - if you know Python, you know Adder.\n- Secured by design (Adder is designed to run untrusted code).\n- Works on both Node.js and Browsers.\n- No need for any sub-processes.\n- Simple \u0026 accessible interface.\n- Easy to extend, and easy to remove builtins and limit.\n- Agnostic to JavaScript changes and versions.\n- Easy to limit memory usage, commands per run, execution time, etc..\n- Caching and Optimizations makes it pretty fast for multiple executions.\n\n## Platforms\n\nAdder works and heavily tested on the following browsers / platforms:\n\n- Chrome 53\n- IE Edge\n- FireFox 45\n- Opera 40\n- Node.js 4.1.1\n\n![platforms](img/supported.png \"Platforms\")\n\n## Install\n\nThere are several ways to install Adder:\n\n#### Via npm\n\n```\nnpm install adder-script\n```\n\n#### Via bower\n\n```\nbower install adder-script\n```\n\n#### Via git (clone)\n\n```\ngit clone https://github.com/RonenNess/adder.git\n```\n\nOr you can download from the [GitHub repository](https://github.com/RonenNess/adder).\n\n#### Building The Code\n\nTo build the distributed version for client side, run the command `build.bat`.\nIt uses `browserify` and `uglifyjs`, so be sure to install them first.\n\n## Tests \u0026 Examples\n\n### Tests\n\nTo run Adder tests, you can open the html file *tests/test.html* in the browser of your choice.\n\nTo test in Node.js, run the following command (requires *Node.js* and *qunit-cli* installed):\n\n```\nqunit-cli tests/test.js\n```\n\n### Performance Tests\n\nTo run performance tests, open the html file *tests/performance.html* in the browser of your choice.\nTo test performance in Node.js, execute file *tests/performance-node.js* in Node.\n\nNote that results may vary from run to run, so its recommended to execute several times and do an average.\n\n### Interactive Shell\n\nTo get an interactive shell and play with the language, you can open *examples/shell.html* in the browser of your choice.\n\n### Sandbox\n\nTo get a rich Adder sandbox with code examples and minimal editor, you can open *examples/sandbox.html* in the browser of your choice.\n\n## Performance\n\nIn overall, Adder appears to be 3-5 times slower than executing plain JavaScript, **on multiple executions**. On FireFox it appears to be much faster, due to caching of expressions.\n\nThe following is a summary of performance tests I conducted on multiple browsers (with windows 8). In bars below less is better:\n\n\n![Performance table](img/performance.png \"Performance table\")\n\nThese tests execute the same logic with Adder and JavaScript couple thousands of times, and measure the time it took to execute each code.\n\nPlease note:\n\n- The tests above don't include compile time (Adder scripts are compiled prior the tests).\n- Adder programs that execute multiple times have internal caching which makes them faster. If your project run each Adder program only once, performance would be slightly worse.\n\nFor more info check out *tests/performance.html*.\n\n___\n\n# Executing Adder - Host application side\n\nThis part of the docs explain how to setup and execute Adder from the host application side, eg the client JavaScript or your Node.js server.\n\nLater in these docs we'll learn the language itself and how to write Adder scripts.\n\n\n## Quick Example\n\nBefore diving into the APIs, lets start with a simple example:\n\n```JavaScript\n// init Adder environment (connect output to alerts)\nAdderScript.init({\n    outputFunc: function(text) {alert(\"output from script: \" + text);},\n});\n\n// create a simple script and compile it\ncompiledCode = AdderScript.compile('print(\"Hello World!\")');\n\n// spawn a program and execute it\n// the result will be an alert with the text \"Hello World!\".\nvar program = AdderScript.newProgram(compiledCode);\nprogram.execute();\n```\n\nPretty simple right? Now lets dive in a little deeper.\n\n## Init Environment\n\nTo run Adder scripts you first need to init environment:\n\n```JavaScript\n// if you don't provide any params output will go to console.log and default flags will apply\nAdderScript.init();\n```\n\n## Compile Code\n\nOnce the environment is ready, you can compile Adder codes using the compile function:\n\n```JavaScript\nvar compiled = AdderScript.compile(someCodeString);\n```\n\n## Save / Load pre-compiled code\n\nIf you want to save the compiled code for later usage, you can simply JSON.stringify() it into a file:\n\n```JavaScript\n// require fs\nvar fs = require('fs');\n\n// save compiled code:\nfs.writeFile(filename, JSON.stringify(compiledCode), function(err) {\n    // handle errors...\n});\n\n// load compiled code you previously saved\nfs.readFile(filename, 'utf8', function(err, data) {\n    if (err) // handle errors...\n    compiledCode = JSON.parse(data);\n});\n```\n\n## Create \u0026 Execute Programs\n\nAn Adder ```Program``` can be think of as a process executing a single Adder script one or more times.\nHowever, the Adder ```program``` is not a real process but an object living on the same memory space as the host application.\n\nTo spawn a new program from a compiled code, use ```newProgram()```:\n\n```JavaScript\nvar program = AdderScript.newProgram(compiledCode);\n```\n\nThe program will now live in memory and you can execute it as many times as needed and access its internal memory and variables.\n\nExecuting the same program multiple times is much faster than spawning a new program every time, due to caching and internal optimizations.\nIn addition, global scope variables will stay alive between different executions of the same program.\n\nTo execute the program code once, use execute:\n\n```JavaScript\nprogram.execute();\n```\n\nIf you want to clear your program's context (eg remove all user defined variables from global scope), use ```resetContext()```:\n\n```JavaScript\nprogram.resetContext();\n```\n\n## Get values and execution errors\n\nYou can easily access the last evaluated result and get it as a native JavaScript object, using ```getLastValue()```:\n\n```JavaScript\nvar lastVal = program.getLastValue();\n```\n\nIn addition, you can read any variable in the program's global scope using ```getGlobalVar()```:\n\n```JavaScript\n// get variable from global scope as native javascript object\nvar value = program.getGlobalVar(\"var_name\");\n```\n\nOr, you can set any variable in the program's global scope using ```setGlobalVar()```:\n\n```JavaScript\n// set variable in program global scope\nprogram.setGlobalVar(\"var_name\", value, isReadonly);\n```\n\nIn addition, you can check if any error occurred during the last execution, using ```getLastError()```:\n\n```JavaScript\nvar lastError = program.getLastError();\nif (lastError) {\n    console.log(lastError.message);\n}\n```\n\nYou can see all Adder error types in object ```AdderScript.Errors```, or in file *errors.js*.\n\n## Advanced init settings\n\nWhen init Adder environment you can provide a dictionary with the following settings:\n\n```JavaScript\nAdderScript.init({\n    flags: {},                  // different compiler / interpreter flags you can set (explained later).\n    modules: [\"ALL\"],           // which modules to load. ['ALL'] will load all built-in modules.\n    outputFunc: printOutput,    // function to handle scripts output, when print() is called.\n    showDebugConsole: true,     // if true, Adder will dump some extra debug data to console.\n});\n```\n\n### flags\n\nThe following are all the flags you can set when you init Adder environment (as the 'flags' option):\n\n```JavaScript\nvar flags = {\n    stackLimit: 256,                // Stack depth limit. If exceeded will throw 'StackOverflow' exception.\n    maxStatementsPerRun: 2048,      // Maximum statements that can be executed in a single run. If exceeded will throw 'ExceededStatementsLimit' exception.\n    maxStringLen: 5000,             // Maximum allowed string lengths. If exceeded will throw 'ExceedMemoryLimit' exception.\n    maxContainersLen: 1000,         // Maximum values allowed in lists, sets and dictionaries. If exceeded will throw 'ExceedMemoryLimit' exception.\n    maxVarsInScope: 100,            // Limit number of variables allowed per scope. If exceeded will throw 'ExceedMemoryLimit' exception.\n    executionTimeLimit: 1000,       // Time limit for a single execution (in milliseconds). If exceeded will throw 'ExceededTimeLimit' exception.\n    memoryAllocationLimit: 10000,   // Memory limit, very roughly estimated, in bytes (per execution). If exceeded will throw 'ExceedMemoryLimit' exception.\n    removeBuiltins: [],             // An optional list of builtin function and const names you want to remove from the language.\n    throwErrors: false,             // If true, will throw exceptions from Adder execution if occur. If false, you need to check errors with getLastError().\n}\n```\n\n### modules\n\nModules are objects with functions and consts you can access from Adder scripts.\nFor example, there's the built-in *Math* module that provide all the Math-related functionality and consts.\n\nYou can choose which modules are included in your environment to have fine control over which APIs Adder scripts can access.\n\nNote that you cannot import modules from inside Adder script, Adder code can only access what the host application allows it (this is by design).\n\nTo include all modules you can set ```modules``` to ```[\"ALL\"]```.\nHowever, that's not recommended in production, as it will include modules that can pop alerts and write to console (something you normally wouldn't want). \n\nTo load only the \"safe for production\" modules, use ```[\"SAFE\"]```.\n\nAll available modules will be described later in the chapter about writing Adder scripts.\n\n### outputFunc\n\nAn optional function to handle script output when ```print``` is called. For example, if you want to send all ```print``` output directly to console:\n\n```JavaScript\nfunction outputFunc() {\n    console.log(Array.from(arguments).join(\" \"));\n}\n```\n\nNote that this is the default behavior; If no outputFunc is provided, all output will go to console.log by default.\n\n### showDebugConsole\n\nIf set to true, Adder will show some useful debug data in console.\n\n## Register Functions\n\nThe most simple way to extend Adder's API and create an interface to the host application, is via builtin functions.\n\nBuiltin functions are basically functions Adder scripts can call from anywhere (defined in global scope) and will execute hard-coded JavaScript code.\n\nTo register a new builtin function use ```addBuiltinFunction()```:\n\n```JavaScript\n// init AdderScript environment\nAdderScript.init();\n\n// add builtin function\nAdderScript.addBuiltinFunction({name: \"test\",                   // function name\n                                func: function(x) {alert(x)},   // the function itself\n                                requiredParams: 1,              // number of required params\n                                optionalParams: 0});            // number of additional optional params\n```\n\nThe code above will add a builtin function called 'test', that gets one parameter and alert it.\n\nOnce registered, you can use the new function like any other built-in Adder function (the following is an Adder script code):\n\n```Python\n# will alert \"Hello World!\"\ntest(\"Hello World!\")\n```\n\n### Return Complex Objects\n\nIf you want your function to return a dictionary or a complex object, and not just a basic type, you need to use ```toAdderObject``` on the returned value. For example:\n\n```JavaScript\n// the actual function implementation\nfunction testFunc(x) {\n\tAdderScript.toAdderObject(\"testFuncReturnType\", \n\t{\n\t\tfoo: 5,\n\t\tbar: 10,\n\t}, this);\n}\n\n// add builtin function\nAdderScript.addBuiltinFunction({name: \"test\",                   // function name\n                                func: testFunc,   \t\t\t\t// the function itself\n                                requiredParams: 1,              // number of required params\n                                optionalParams: 0});            // number of additional optional params\n```\n\nThen it can be used from Adder like this:\n\n```Python\nret = test()\nif ret.foo == 5:\n    print(\"Success!\")\n```\n\n## Register A Custom Module\n\nJust like registering a builtin function, you can register a custom module to Adder's API.\n\nAs mentioned before, a module is an object containing functions and constants wrapped together under one object.\n\nTo define a custom built-in module:\n\n```JavaScript\n// init AdderScript environment\nAdderScript.init();\n\n// add builtin module\nAdderScript.addBuiltinModule(\"Test\",\n                                  {\n                                    // define a function named 'foo'\n                                    \"foo\": {\n                                        func: function(x) {alert(x)},\n                                        requiredParams: 1,\n                                        optionalParams: 0\n                                     },\n\n                                     // define a const named 'bar' that equals to \"World\"\n                                     \"bar\": \"World\",\n                                  }\n                              );\n```\n\nThe code above will define a module named ```Test``` with a function ```foo()``` and a constant string ```bar```.\n\nOnce defined, you can use the new module just like any other built-in module (the following is an Adder script code):\n\n```Python\n# will alert \"Hello World!\" (Test.bar equals to \"World\")\nTest.foo(\"Hello \" + Test.bar + \"!\")\n```\n\n\n## Define an enum\n\nTo create an enum you can add a custom module with nothing but consts in it. For example:\n\n\n```JavaScript\n// add an enum\nAdderScript.addBuiltinModule(\"Colors\",\n                                  {\n                                    \"Red\": 0,\n\t\t\t\t\t\t\t\t\t\"Blue\": 1,\n\t\t\t\t\t\t\t\t\t\"Green\": 2,\n\t\t\t\t\t\t\t\t\t\"Yellow\": 3,\n                                  }\n                              );\n```\n\nThen from code users can access it as:\n\n```Python\ncolor = Colors.Red\n```\n\n\n## Define a built-in object type\n\nA module acts like a singleton. But what if you need an object you can instantiate, like Adder's ```list```, ```dict``` or ```set```?\n\nTo define a new built-in object type use ```defineBuiltinObject()```:\n\n```JavaScript\n// init AdderScript environment\nAdderScript.init();\n\n// define a new object type \"Person\" and return a function to instantiate it\ncreatePerson = AdderScript.defineBuiltinObject(\"Person\", {\n                                    \"say_hello\": {\n                                        func: function() {alert(\"Hello World!\")},\n                                        requiredParams: 0,\n                                        optionalParams: 0\n                                     },\n                                     \"race\": \"human\",\n                                  });\n\n// now you can use 'createPerson' to create a new 'Person' instances.\n// however, you still need to provide an API for Adder to create it.\n// lets register a new built-in function, \"create_person\", that will use 'createPerson' to create a new 'Person' instance:\nAdderScript.addBuiltinFunction({name: \"create_person\",                          // function name\n                                func: function(x) {return createFunc(this)},    // the function itself to create Person.\n                                requiredParams: 0,              // number of required params\n                                optionalParams: 0});            // number of additional optional params\n```\n\nNote that 'createPerson' function expect to get 'this' as param, where 'this' is any built-in function or module.\n\nNow you can create and use the new 'Person' objects from Adder scripts (the following is an Adder script code):\n\n```Python\n# will create a new person and call its function 'say_hello()'\na = create_person()\na.say_hello()\n```\n\n___\n\n\n# Writing Adder Scripts\n\nPreviously we learned how to execute adder scripts and interact with them from the host application side.\nIn this part of the tutorial we'll learn how to actually write Adder scripts.\n\n## Basic Syntax\n\nAdder syntax is the same as [Python](https://www.python.org), so if you know Python you know Adder and can skip this part.\n\nIf you are not familiar with Python, here's a quick summary (after this you will also be able to use Python!).\n\n### Indentation\n\nAdder is indent-sensitive; indentation is used to open and close blocks (instead of curly brackets in other languages).\n\nLets take a look at an example with ```if``` and ```else``` blocks:\n\n```Python\nif a == 5:\n    print(\"this is the if block\")\nelse:\n    print(\"this is the else block\")\n```\n\nIndents must be multiply of 4 spaces. Wrong indentation will throw syntax errors.\n\n### Comments\n\nComments in Adder begin with the hash character (\"#\") and are terminated by the end of line:\n\n```Python\n# this is a comment line\n\na = 5 # this part is also a comment; after 'a = 5' is executed this part will be ignored.\n```\n\n### Variables\n\nTo create a new variable you just need to assign a value to it:\n\n```Python\na = 5\n```\n\nVariables in Adder are loosely typed, meaning you can change the type on the fly:\n\n```Python\na = 5       # 'a' is a number.\na = \"foo\"   # now 'a' is a string.\na = True    # and now 'a' is a boolean.\n```\n\n#### Variables \u0026 Scopes\n\nIf 'a' is defined in a parent's block, setting its value will override it. For example:\n\n```Python\n# define variable 'a' in parent block\na = 5\n\n# override the variable 'a' from inside the 'if' block\nif True:\n    a = 6\n\n# print 'a', which should now be '6'\nprint(a)\n```\n\nIn addition, if you assign a variable inside a function that also exist in global scope, you will override it:\n\n```Python\n# define global variable 'a'\na = 5\n\n# define a function that override global variable 'a' with another value\ndef test():\n    a = 6\n\n# call the function that will change the value of 'a'\ntest()\n\n# print 'a' that should now be '6'\nprint(a)\n```\n\nIf you are familiar with Python you will notice this behavior is slightly different;\nIn Python, you need to use the ```global``` statement to override global variables from inside a function. In Adder, all variable assignment is ```global``` by default.\n\n### String variables\n\nString variables have an extended API that normal variables don't share.\nThis API contains useful query and string manipulation functions:\n\n#### len ()\n\nReturn string length.\n\nFor example:\n\n```Python\n\"hello world\".len()  # \u003c-- return 11.\n```\n\n#### split ([delimiter])\n\nBreak the string into a list of string, separated by a given delimiter (or space if not provided).\n\nFor example:\n\n```Python\n\"hello world\".split()       # \u003c-- return list(\"hello\", \"world\").\n\"hello-world\".split(\"-\")    # \u003c-- return list(\"hello\", \"world\").\n\"hello-world\".split(\"+\")    # \u003c-- return list(\"hello-world\"), since delimiter not found.\n```\n\n#### replace (search, replace)\n\nReplace all occurrences of a search term with a given string.\n\nFor example:\n\n```Python\n\"hello world\".replace(\"world\", \"friends\")  # \u003c-- return \"hello friends\".\n```\n\n#### remove (search, replace)\n\nRemove all occurrences of a search term.\n\nFor example:\n\n```Python\n\"hello world\".remove(\"world\")  # \u003c-- return \"hello \".\n```\n\n#### index (search)\n\nReturn the index of a search term in string, or -1 if not found.\n\nFor example:\n\n```Python\n\"hello world\".index(\"world\")  # \u003c-- return 6.\n\"hello world\".index(\"dog\")    # \u003c-- return -1.\n```\n\n#### has (search)\n\nReturn string containing a search term (equivalent to ```x in string```).\n\nFor example:\n\n```Python\n\"hello world\".has(\"world\")  # \u003c-- return True.\n```\n\n#### count (search)\n\nCount how many times a search term appears in the string.\n\nFor example:\n\n```Python\n\"hello world, its a beautiful world!\".count(\"world\")  # \u003c-- return 2.\n```\n\n#### trim ()\n\nRemove all white spaces from the begining and the end of the string.\n\nFor example:\n\n```Python\n\"     hello world!    \".trim()  # \u003c-- return \"hello world!\".\n```\n\n#### hash ()\n\nReturn a numeric hash value of the string.\n\nFor example:\n\n```Python\n\"hello world\".hash()  # \u003c-- return 1794106052.\n```\n\n#### starts_with (word)\n\nReturn true if string starts with a given search term.\n\nFor example:\n\n```Python\n\"hello world\".starts_with(\"hello\")  # \u003c-- return True.\n\"hello world\".starts_with(\"world\")  # \u003c-- return False.\n```\n\n#### ends_with (word)\n\nReturn true if string ends with a given search term.\n\nFor example:\n\n```Python\n\"hello world\".ends_with(\"world\")  # \u003c-- return True.\n\"hello world\".ends_with(\"hello\")  # \u003c-- return False.\n```\n\n#### is_alpha ()\n\nReturn true if string contains only alphabetic characters in English.\n\nFor example:\n\n```Python\n\"helloworld\".is_alpha()   # \u003c-- return True.\n\"hello world\".is_alpha()  # \u003c-- return False (because of the space).\n\"helloworld2\".is_alpha()  # \u003c-- return False (because of the '2').\n```\n\n#### is_digit ()\n\nReturn true if string contains only numeric digits.\n\nFor example:\n\n```Python\n\"123\".is_digit()        # \u003c-- return True.\n\"123 45\".is_digit()     # \u003c-- return False (because of the space).\n\"12a34\".is_digit()      # \u003c-- return False (because of the 'a').\n```\n\n#### lower ()\n\nConvert string to lower case.\n\nFor example:\n\n```Python\n\"HeLlo WoRlD!\".lower()  # \u003c-- return \"hello world!\".\n```\n\n#### upper ()\n\nConvert string to upper case.\n\nFor example:\n\n```Python\n\"HeLlo WoRlD!\".upper()  # \u003c-- return \"HELLO WORLD!\".\n```\n\n#### title ()\n\nConvert string to title case.\n\nFor example:\n\n```Python\n\"HeLlo WoRlD!\".upper()  # \u003c-- return \"Hello World!\".\n```\n\n#### slice (start, [len])\n\nReturn a slice of the string.\n\nFor example:\n\n```Python\n\"Hello world!\".slice(3)  # \u003c-- return \"lo world!\" (when no length provided, slice until end).\n\"Hello world!\".slice(3, 5)  # \u003c-- return \"lo wo\" (because length is limited to 5).\n```\n\n### Builtin Consts\n\nA small number of Adder constants live in the global scope. They are:\n\n#### False\nThe false value of the bool type. Assignments to False are illegal and will raise a SyntaxError.\n\n#### True\nThe true value of the bool type. Assignments to True are illegal and will raise a SyntaxError.\n\n#### None\nNone is frequently used to represent the absence of a value, as when default arguments are not passed to a function.\nAssignments to None are illegal and will raise a SyntaxError.\n\n#### NaN\nNaN (Not a Number) is a special constant that represent an illegal expressions involving numbers and non-number values.\nFor example, ```5 * \"a\"``` will return NaN (note however that ```5 * \"2\"``` will be evaluated as '5 * 2' and return 10).\n\n#### __VERSION__\nString, the current Adder Script version.\n\n### Operators\n\nThis chapter describe all the language arithmetic and comparison operators.\n\n#### Basic Arithmetic Operators\n\nIn adder all the basic arithmetic operators are supported - add, subtract, multiply, divide and modulate:\n\n```Python\na = 5 + 2\nb = 4 - 2\nc = 6 / 3\nd = 2 * 15\ne = 5 % 2\n```\n\nIn addition, there's a built-in operator for power, represented by ```**```:\n\n```Python\na = 2 ** 3   # equals to '2 * 2 * 2'\n```\n\n#### In-place operators\n\nIn-place operators are syntactic sugar to change the value of a variable:\n\n```Python\na += 1  # the same as \"a = a + 1\"\nb -= 1  # the same as \"b = b - 1\"\nc /= 2  # the same as \"c = c / 2\"\nd *= 2  # the same as \"d = d * 2\"\n```\n\nMost arithmetic operators have their own in-place version.\n\n#### Comparison operators\n\nAdder support all the basic comparison operators: ```\u003e```, ```\u003c```, ```\u003e=```, ```\u003c=```, ```!=```, ```==```.\nThey work the same as in most programming language:\n\n```Python\n2 \u003c 5  # true\n5 \u003e 20 # false\n2 == 2 # true\n3 \u003e= 2 # true\n5 \u003c= 4 # false\n5 != 2 # true\nTrue != False # true\nlist(1) == list(1) # true\nlist(1) == list(2) # false\n```\n\n#### Bitwise operators\n\nTo perform bitwise `and` operation, use the ```\u0026``` operator:\n\n```Python\nprint(36 \u0026 14) # will print '4'\n```\n\nTo perform bitwise `or` operation, use the ```|``` operator:\n\n```Python\nprint(36 | 14) # will print '46'\n```\n\n#### not\n\nThe ```not``` operator invert a boolean value, eg turn ```true``` into ```false``` and vice-versa:\n\n```Python\nif not True:\n    print(\"hello!\")\n```\n\n#### or\n\nTo create a conditional 'or', use the ```or``` operator:\n\n```Python\na = 5\nif a == 1 or a == 5:\n    print(\"a is either 1 or 5\")\n```\n\nNote that ```or``` doesn't necessarily return a boolean (true / false), it returns the first value that when cast to boolean will return ```true```.\nThis means you can also use ```or``` to assign the first value option.\n\nFor example:\n\n```Python\n# this will print \"yay!\", the first value considered as 'true' when casted as boolean\na = False or None or \"yay!\" or True\nprint(a)\n```\n\n#### and\n\nTo create a conditional 'and', use the ```and``` operator:\n\n```Python\na = 1\nb = 2\nif a == 1 and b == 2:\n    print(\"a is 1 and b is 2\")\n```\n\nWith ```and``` operator the condition is met only if all parts are true.\n\n#### in\n\nIn General, ```in``` is used to check if a value is contained in an object.\n\nFor example, with lists ```in``` will return true if the list contain the given value:\n\n```Python\nlst = list(1,2,3)\nif 1 in lst:\n    print(\"'1' is in the list!\")\n```\n\nWith dictionaries, ```in``` will return true if value is a key inside the dictionary.\n\n```Python\ndct = dict()\ndct.set(\"a\", \"hello\")\nif \"a\" in dct:\n    print(\"'a' is a key inside the dictionary!\")\n```\n\n#### not in\n\n```not in``` is a syntactic sugar to test if a value is *not* in another value:\n\n```Python\nlst = list(1,2,3)\nif 5 not in lst:\n    print(\"5 is not in the list!\")\n```\n\n#### is\n\n```is``` operator is used to check if two values are the same object, or strictly equal. For example:\n\n```Python\n5 is 5              # true\nTrue is True        # true\nlist() is list()    # false - not the same object\n4 is 5              # false\n0 is False          # false\na = list(); a is a  # true\n```\n\n#### is not\n\nAs a syntactic sugar, to test if value is not the same object as other value. For example:\n\n```Python\na = list()\nb = list()\nif a is not b:\n    print(\"'a' is not 'b'!\")\n```\n\n### Conditions (if, else, elif)\n\nConditions test an expression and determine weather or not to execute the following block.\n\n#### if\n\nTo write a conditional block, you use the ```if``` statement:\n\n```Python\nif a == 5:\n    print(\"'a' equals 5\")\n```\n\nIn the example above the block following the statement will only be executed if the condition (```a == 5```) is met.\n\n```inline if``` statements are also valid:\n\n```Python\nif a == 5: print(\"'a' equals 5\")\n```\n\n#### else\n\n```else``` statements will execute their following block only if the last ```if``` condition was false.\n\nFor example:\n\n```Python\nif a == 5:\n    print(\"'a' equals 5\")\nelse:\n    print(\"'a' does not equal 5\")\n```\n\n#### elif\n\nIt is possible to add a conditional ```if``` to any ```else``` statement, eg make a block that will execute only if the previous ```if``` was false *and* a new condition is met.\n\nTo create an else condition (can be think of as ```else if```), use the ```elif``` statement:\n\n```Python\nif a == 5:\n    print(\"'a' equals '5'\")\nelif a == 6:\n    print(\"'a' equals '6'\")\nelse:\n    print(\"a is neither '5' nor '6'\")\n```\n\n### Loops\n\nThere are two ways to make loops / iterate in Adder. We'll explain them in this chapter.\n\n#### for\n\n```for``` statement iterate over the values of a container. For example, to iterate over the values of a list:\n\n```Python\na = list(1,2,3)\nfor i in a:\n    print(i)\n```\n\n#### while\n\n```while``` statement will repeat the block as long as the condition is true:\n\n```Python\na = 5\nwhile a \u003e 0:\n    print(a)\n    a -= 1\n```\n\n### Functions\n\nTo define a new function, use the ```def``` statement:\n\n```Python\n# define the function\ndef hello_world():\n    print(\"Hello World!\")\n\n# use it\nhello_world()\n```\n\nOr with params:\n\n```Python\n# define the function\ndef hello_someone(name):\n    print(\"Hello \" + name)\n\n# use it\nhello_someone(\"Bob\")\n```\n\n## Containers (list, set, dict)\n\nThere are 3 built-in containers you should know in Adder:\n\n### List\n\nList hold a list of values, while preserving the order of insertion.\n\nTo create a new list:\n\n```Python\n# create an empty list\na = list()\n\n# create a list with starting values: 1,2,3\na = list(1,2,3)\n```\n\nThe list API is slightly different than Python's list.\nA list instance have the following functions:\n\n#### clone ()\n\nCreate a shallow copy of the list.\n\nFor example:\n\n```Python\na = list(1,2,3)\nb = a.clone()  # \u003c-- 'b' will now be equal to 'a', but not the same object.\n```\n\n#### empty ()\n\nReturn true if the list is empty, false otherwise.\n\nFor example:\n\n```Python\na = list()\nif a.empty():\n    print(\"List is empty!\")\n```\n\n#### to_set ()\n\nConvert the list to a Set object (described later).\n\nFor example:\n\n```Python\na = list(1, 2, 3)\nb = list.to_set()  # \u003c-- 'b' is now a set with values 1, 2 and 3.\n```\n\n#### len ()\n\nReturn list length.\n\nFor example:\n\n```Python\na = list(1,2)\nprint(a.len())  # \u003c-- will print '2'.\n```\n\n#### append (val)\n\nAdd a value to the end of the list.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\")\na.append(\"foobar\")  # \u003c-- list will now contain: \"foo\", \"bar\", \"foobar\".\n```\n\n#### has (val)\n\nReturn if the list contains a given value.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\")\nif a.has(\"foo\"):\n    print(\"List have value 'foo'\")\n```\n\n#### clear ()\n\nClear the list (remove all values from it).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\")\na.clear()  # \u003c-- 'a' will now be an empty list.\n```\n\n#### count (val)\n\nReturn how many times a given value appears in the list.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"foo\", \"hello\")\nprint(a.count(\"foo\"))  # \u003c-- will print 2 (\"foo\" appears twice in list).\n```\n\n#### extend (other)\n\nExtend this list with another list (like concat).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\")\nb = list(\"hello\", \"world\")\na.extend(b)  # \u003c-- 'a' will be a list with: \"foo\", \"bar\", \"hello\", \"world\". 'b' will remain unchanged.\n```\n\n#### index (val)\n\nReturn the first index of a given value in the list (or -1 if value not found).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"hello\")\nprint(a.index(\"bar\"))  # \u003c-- will print '1', the index of \"foo\".\nprint(a.index(\"other\"))  # \u003c-- will print '-1', since \"other\" is not in list.\n```\n\n#### insert (val, position)\n\nAdd a value to the list at a given position (index).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\")\na.insert(\"hello\", 1)  # \u003c-- 'a' will now contain: \"foo\", \"hello\", \"bar\".\n```\n\n#### pop ([position])\n\nRemove and return the last value from list, or from a given position (if provided position argument).\n\nFor example:\n\n```Python\n# using pop without position param\na = list(\"foo\", \"bar\", \"hello\")\na.pop()  # \u003c-- will remove and return \"hello\", which is the last value in the list.\n\n# using pop with position param\na = list(\"foo\", \"bar\", \"hello\")\na.pop(1)  # \u003c-- will remove and return \"bar\", which is the value with index 1 in the list.\n```\n\n#### shift ()\n\nRemove and return the first value from the list.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"foobar\")\na.shift()  # \u003c-- will remove and return \"foo\", the first value in the list.\n```\n\n#### remove (val)\n\nRemove a given value from list (if found).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"hello\")\na.remove(\"bar\")  # \u003c-- will remove \"bar\" from the list.\n```\n\n#### reverse ()\n\nReverse the list.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"hello\")\na.reverse()  # \u003c-- 'a' will now contain: \"hello\", \"bar\", \"foo\".\n```\n\n#### slice (start, [end])\n\nReturn a segment of the list from a starting position and an optional ending position (ending position value will not be included).\n\nFor example:\n\n```Python\nfruits = list(\"Banana\", \"Orange\", \"Lemon\", \"Apple\", \"Mango\")\nprint(fruits.slice(1, 3))  # \u003c-- will print \"Orange,Lemon\".\n```\n\n#### join ([delimiter])\n\nConvert the list to a string with an optional delimiter (if delimiter is not provided, a comma will be used).\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"hello\")\nprint(a.join(\"--\"))  # \u003c-- will print \"foo--bar--hello\".\n```\n\n#### sort ()\n\nSort the list values by a default string sorting.\n\nFor example:\n\n```Python\na = list(\"b\", \"c\", \"a\")\na.sort()  # \u003c-- 'a' will now contain: \"a\", \"b\", \"c\".\n```\n\n#### at (position)\n\nReturn value from a given position in list.\n\nFor example:\n\n```Python\na = list(\"foo\", \"bar\", \"hello\")\nprint(a.at(1))  # \u003c-- will print \"bar\"\n```\n\n#### Iterating lists\n\nTo iterate over the values in a List, use ```for-in``` loop:\n\n```Python\na = list(\"foo\", \"bar\", \"foobar\")\nfor val in a:\n    print(val)\n```\n\n\n### Set\n\nA Set is like a list, but in a set each value may only appear once. In addition, a Set may only contain simple types and not objects.\nSets are much faster when you need to check if values exist or not.\n\nTo create a new set:\n\n```Python\n# create an empty set\na = set()\n\n# create a set with starting values: \"Apple\", \"Banana\", \"Orange\"\na = set(\"Apple\", \"Banana\", \"Orange\")\n```\n\nThe set API is slightly different than Python's set.\n\nA set instance have the following functions:\n\n#### clone ()\n\nCreate a shallow copy of the set.\n\nFor example:\n\n```Python\na = set(1,2,3)\nb = a.clone()  # \u003c-- 'b' will now be equal to 'a', but not the same object.\n```\n\n#### empty ()\n\nReturn true if set is empty, false otherwise.\n\nFor example:\n\n```Python\na = set()\nif a.empty():\n    print(\"Set 'a' is empty!\")\n```\n\n#### to_list ()\n\nConvert the set to a List object.\n\nFor example:\n\n```Python\na = set(1, 2, 3)\nb = a.to_list()  # \u003c-- 'b' is now a new list with values 1, 2, 3.\n```\n\n#### len ()\n\nReturn set length.\n\nFor example:\n\n```Python\na = set(1,2)\nprint(a.len())  # \u003c-- will print '2'.\n```\n\n#### add (val)\n\nAdd a value to the end of the set. If value already exist in set, will not do anything (as sets may only contain each value once).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\")\na.add(\"foobar\")  # \u003c-- set will now contain: \"foo\", \"bar\", \"foobar\".\n```\n\n#### has (val)\n\nReturn if the set contains a given value.\n\nFor example:\n\n```Python\n# create a set\na = set(\"foo\", \"bar\")\n\n# check if contains a value\nif a.has(\"foo\"):\n    print(\"'foo' is in set\")\n```\n\nNote that ```has``` is equivilant of using the ```in``` operator:\n\n```Python\nif \"foo\" in set(\"foo\", \"bar\"):\n    print(\"'foo' is in set\")\n```\n\n#### clear ()\n\nClear the set (remove all values from it).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\")\na.clear()  # \u003c-- set will now be an empty set.\n```\n\n#### extend (other)\n\nExtend this set with another set (like concat).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\")\nb = set(\"hello\", \"world\")\na.extend(b)  # \u003c-- 'a' will be a set with: \"foo\", \"bar\", \"hello\", \"world\". 'b' will remain unchanged.\n```\n\n#### index (val)\n\nReturn the index of a given value in set (or -1 if value not found).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\", \"hello\")\nprint(a.index(\"bar\"))  # \u003c-- will print '1', the index of \"foo\".\nprint(a.index(\"other\"))  # \u003c-- will print '-1', since \"other\" is not in list.\n```\n\n#### remove (val)\n\nRemove a given value from the set (if found).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\", \"hello\")\na.remove(\"bar\")  # \u003c-- will remove \"bar\" from the set.\n```\n\n#### join ([delimiter])\n\nConvert the set to a string connected with a given delimiter (if delimiter is not provided, a comma will be used).\n\nFor example:\n\n```Python\na = set(\"foo\", \"bar\", \"hello\")\nprint(a.join(\"--\"))  # \u003c-- will print \"foo--bar--hello\".\n```\n\n#### Iterating sets\n\nTo iterate over the values in a Set, use the ```for-in``` loop:\n\n```Python\na = set(\"foo\", \"bar\", \"foobar\")\nfor val in a:\n    print(val)\n```\n\n### Dictionary\n\nA dictionary, often known as “associative arrays” or \"hash table\", is a table of string keys leading to values.\n\nTo create a new dictionary:\n\n```Python\n# create an empty dictionary\na = dict()\n\n# set a value\na.set(\"key\", \"value\")\n\n# get a value\na.get(\"key\")\n```\n\nThe dictionary API is slightly different than Python's dictionary.\n\nA dictionary instance have the following functions:\n\n#### clone ()\n\nCreates a shallow copy of the dictionary.\n\nFor example:\n\n```Python\na = dict()\nb = a.clone()  # \u003c-- 'b' will now be equal to 'a', but not the same object.\n```\n\n#### set (key, value)\n\nAdd a key-value to the dictionary.\n\nFor example:\n\n```Python\na = dict()\na.set(\"key\", \"value\")  #  \u003c-- dict will now contain a single key, \"key\", that will lead to the value \"value\".\n```\n\n#### get (key, [default])\n\nGet a value from the dictionary by key.\nIf key is not found in dictionary, ```default``` will be returned. If no ```default``` argument is provided, ```None``` will be returned instead.\n\nFor example:\n\n```Python\n# create the dictionary and add value\na = dict()\na.set(\"key\", \"value\")\n\n# get values that exists\nprint(a.get(\"key\"))  # \u003c-- will print \"value\"\n\n# get non-existing value without default\nprint(a.get(\"some-key\"))  # \u003c-- will print None (empty string in default sandbox implementation)\n\n# get non-existing value with default\nprint(a.get(\"some-key\", \"not-found\"))  # \u003c-- will print \"not-found\"\n```\n\n#### keys ()\n\nReturn a list with all keys in the dictionary.\n\nFor example:\n\n```Python\na = dict()\na.set(\"foo\", 1)\na.set(\"bar\", 2)\n\nprint(a.keys())  # \u003c-- will print \"foo,bar\"\n```\n\n#### values ()\n\nReturn a list with all values in the dictionary.\n\nFor example:\n\n```Python\na = dict()\na.set(\"foo\", 1)\na.set(\"bar\", 2)\n\nprint(a.values())  # \u003c-- will print \"1,2\"\n```\n\n#### len ()\n\nReturn how many keys are in the dictionary.\n\nFor example:\n\n```Python\n# create the dictionary\na = dict()\na.set(\"foo\", 1)\na.set(\"bar\", 2)\n\n# print its length\nprint(a.len())  # \u003c-- will print 2.\n```\n\n#### remove (key)\n\nRemove a key from the dictionary.\n\nFor example:\n\n```Python\na = dict()\na.set(\"foo\", 1)\n\na.remove(\"foo\")  # \u003c-- will remove \"foo\" from the dictionary.\na.remove(\"bla\")  # \u003c-- won't do anything, since \"bla\" doesn't exist.\n```\n\n#### clear ()\n\nClear the dictionary completely, leaving it empty.\n\nFor example:\n\n```Python\na = dict()\na.set(\"foo\", 1)\na.clear()  # \u003c-- 'a' will now be an empty dictionary.\n```\n\n#### empty ()\n\nReturn if the dictionary is empty, eg if it has no keys in it.\n\nFor example:\n\n```Python\na = dict()\nif a.empty():\n    print(\"Dictionary is empty!\")\n```\n\n#### has (key)\n\nReturn if the dictionary have a given key.\n\nFor example:\n\n```Python\n# create dictionary\na = dict()\na.set(\"foo\", \"bar\")\n\n# check if key exists in it\nif a.has(\"foo\"):\n    print(\"There's a key 'foo' in dictionary!\")\n```\n\nNote that using ```has()``` is equivalent to using the ```in``` operator:\n\n```Python\n# create dictionary\na = dict()\na.set(\"foo\", \"bar\")\n\n# check if key exists in it\nif \"foo\" in a:\n    print(\"There's a key 'foo' in dictionary!\")\n```\n\n#### extend (other)\n\nExtend this dictionary with another dictionary (like concat).\n\nFor example:\n\n```Python\na = dict()\na.set(\"foo\", \"bar\")\n\nb = dict()\nb.set(\"hello\", \"world\")\n\na.extend(b)  # \u003c-- 'a' will be a dictionary with: \"foo\" = \"bar\", \"hello\" = \"world\". 'b' will remain unchanged.\n```\n\n#### Iterating dictionaries\n\nTo iterate over the keys of a dictionary, use a ```for``` loop:\n\n```Python\n# create dictionary with values\na = dict()\na.set(\"foo\", \"bar\")\na.set(\"hello\", \"world\")\n\n# iterate dictionary and print it\nfor key in a:\n    print(\"Key: \" + key + \", \" + \"Value: \" + a.get(key))\n```\n\n## Built-ins\n\nAdder have a set of built-in functions in global scope that provide some basic language functionality.\nThe built-in functions you should know are:\n\n### print (...)\n\nPrint output (either a single or multiple string messages to print).\n\nThe default ```print``` implementation uses console.log, however the host application may override it using the 'outputFunc' init option.\n\nFor example:\n\n```Python\nprint(\"Hello World!\")\n```\n\n### all (...)\n\nReturn true only if all given values are true or can be evaluated as boolean true.\n\nFor example:\n\n```Python\nprint(all(1, True, Math))  # print True\nprint(all(1, True, Math, None))  # print False, because of the 'None' in the end\n```\n\n### any (...)\n\nReturn true if any of the given values is true or can be evaluated as boolean true.\n\nFor example:\n\n```Python\nprint(any(0, True, None))  # print true, thanks to the second 'True' value\nprint(any(0, 1, None))  # print true, thanks to the second '1' value, which casts to true\nprint(any(0, False, None))  # print false, because none of the values are true\n```\n\n### bin (num)\n\nReturn a binary representation of a number (as string).\n\nFor example:\n\n```Python\nprint(bin(15))  # will print \"1111\"\n```\n\n### bool (val)\n\nCast any value to a boolean (either ```True``` or ```False```).\n\nFor example:\n\n```Python\nprint(bool(False)) # False\nprint(bool(True))  # True\nprint(bool(NaN))   # False\nprint(bool(0))     # False\nprint(bool(False)) # False\nprint(bool(1))     # True\nprint(bool(\"Foo\")) # True\nprint(bool(Math))  # True\n```\n\n### callable (val)\n\nReturn true if given variable is a callable function.\n\nFor example:\n\n```Python\nprint(callable(bin))        # will print \"True\"\nprint(callable(Math.abs))   # will print \"True\"\n\ndef test(): pass\nprint(callable(test))  # will print \"True\"\n\nprint(callable(5))      # will print \"False\"\nprint(callable(True))   # will print \"False\"\nprint(callable(None))   # will print \"False\"\n```\n\n### chr (num)\n\nConvert a number to its ASCII character.\n\nFor example:\n\n```Python\nprint(chr(97))  # \u003c-- will print 'a'\n```\n\n### cmp (x, y)\n\nCompare two numeric values.\nReturns the sign of the difference of two numbers: -1 if x \u003c y, 0 if x == y, or 1 if x \u003e y.\n\nFor example:\n\n```Python\ncmp(1, 2)  # \u003c-- returns -1\ncmp(1, 1)  # \u003c-- returns 0\ncmp(2, 1)  # \u003c-- returns 1\n```\n\n### float (val)\n\nConvert an int or a string to a float.\n\nFor example:\n\n```Python\nprint(float(\"4.3\") + 0.2)  # \u003c-- will print 4.5\n```\n\n### int (val)\n\nConvert a float or a string to an int.\n\nFor example:\n\n```Python\nprint(int(\"4\") + 1)  # \u003c-- will print 5\n```\n\n### len (val)\n\nReturn the length of an object (depends on object type).\nThis is equivalent to ```val.len()```.\n\nFor example:\n\n```Python\na = list(1,2,3)\nprint(len(a))  # \u003c-- will print 3\n```\n\n### ord (chr)\n\nReturn the ASCII value of a character.\n\nFor example:\n\n```Python\nprint(ord('a'))  # \u003c-- will print 97\n```\n\n### range ([start], end, [step])\n\nReturn a list containing the values between a given starting point, ending point, and with an optional step size.\n\nThis method is extremely useful with ```for``` loops.\n\nFor example:\n\n```Python\n# will print numbers 0 to 9 (including). total of 10 iterations.\nfor i in range(10):\n    print(i)\n\n# will print numbers 5 to 7 (including). total of 3 iterations.\nfor i in range(5, 8):\n    print(i)\n\n# will print numbers 0 to 9 (including), with steps of 2. total of 5 iterations.\nfor i in range(0, 10, 2):\n    print(i)\n\n# will create a list with values 0-9 (including).\na = range(10)\n```\n\n### str (obj)\n\nConvert an object or value to a string.\n\nFor example:\n\n```Python\nstr(95)            # \u003c-- return \"95\".\nstr(list(1,2,3))   # \u003c-- return \"1,2,3\".\nstr(None)          # \u003c-- return \"\" (empty string).\nstr(True)          # \u003c-- return \"true\".\nstr(\"foo\")         # \u003c-- return \"foo\".\n```\n\n### repr (obj)\n\nReturn the language representation of an object, as a string.\n\nFor example:\n\n```Python\nrepr(95)            # \u003c-- return \"95\".\nrepr(list(1,2,3))   # \u003c-- return \"list(1,2,3)\".\nrepr(None)          # \u003c-- return \"None\".\nrepr(True)          # \u003c-- return \"True\".\nrepr(\"foo\")         # \u003c-- return '\"foo\"' (with quotes)\n```\n\n### type (obj)\n\nReturn the type of the object.\n\nFor example:\n\n```Python\ntype(\"string\")  # \"string\"\ntype(4)         # \"number\"\ntype(False)     # \"boolean\"\ntype(None)      # \"none\"\ntype(ord)       # \"function\"\ntype(Math)      # \"module\"\ntype(list())    # \"list\"\ntype(set())     # \"set\"\ntype(dict())    # \"dict\"\ntype(5 * \"str\") # \"NaN\"\n```\n\n### list (...)\n\nCreate a new list with optional starting values.\n\nFor example:\n\n```Python\na = list()\nb = list(1,2,3)\n```\n\n### set (...)\n\nCreate a new set with optional starting values.\n\nFor example:\n\n```Python\na = set()\nb = set(1,2,3)\n```\n\n### dict ()\n\nCreate a new empty dictionary.\n\nFor example:\n\n```Python\na = dict()\n```\n\n### reversed (lst)\n\nReverse a list copy, without changing the original list.\nThis is equivalent to ```a.clone().reverse()```.\n\nFor example:\n\n```Python\na = list(1,2,3)\nb = reversed(a)\nprint(a)  # \u003c-- will print \"1,2,3\"\nprint(b)  # \u003c-- will print \"3,2,1\"\n```\n\n### equal (a, b)\n\nReturn ```True``` if both values are equal, ```False``` otherwise.\nThis is equivalent to ```a == b```, but usable as a function, so you can do things like ```compare_func = equal``` and later use 'compare_func' or override it.\n\nFor example:\n\n```Python\na = list(1,2,3)\nb = list(1,2,3)\nif equal(a, b):\n    print(\"Lists are equal!\")\n```\n\n### dir ([obj])\n\nReturn all the keys in current scope or in object's API.\n\nThis function should not be used for production purposes, its mostly useful to examine objects in shell.\n\nFor example:\n\n```Python\n# will print everything in global scope\nprint(dir())\n\n# will print the API functions and vars of the 'Math' module\nprint(dir(Math))\n```\n\n### delete (obj)\n\nRemove a variable.\n\nFor example:\n\n```Python\na = 5\ndelete(a)  # \u003c-- 'a' will no longer exist after this.\n```\n\n### exist (obj)\n\nReturn ```True``` if variable name exists in current scope or globals.\n\nFor example:\n\n```Python\nif exist(\"a\"):\n    print(\"'a' exists: \" + a)\n```\n\n## Modules\n\nModules are objects with built-in functions and constants that Adder scripts can access and use.\n\nWhen setting up the environment (on your host application), you can choose which modules to import and can even register your own modules (this described in details in previous chapters).\n\nYou use modules with the dot notation:\n\n```Python\na = Math.abs(-5)\n```\n\nAll modules act like a global singleton class.\n\nIn this chapter we'll go over the basic built-in modules and describe their APIs.\n\n### Math\n\nProvide basic math-related functionality and constants.\n\nThe Math module provide the following API:\n\n#### abs (val)\n\nConvert a number to its absolute value.\n\nFor example:\n\n```Python\nMath.abs(-5)  # \u003c-- will return 5.\n```\n\n#### min (...)\n\nGet a list of numeric arguments (or a single list argument) and return the smallest value.\n\nFor example:\n\n```Python\nMath.min(1, 5)  # \u003c-- will return 1.\nMath.min(list(1, 5))  # \u003c-- will return 1.\nMath.min(list(1, 2), 5)  # \u003c-- will return NaN - can't mix numeric and list arguments.\n```\n\n#### max (...)\n\nGet a list of numeric arguments (or a single list argument) and return the largest value.\n\nFor example:\n\n```Python\nMath.max(1, 5)  # \u003c-- will return 5.\nMath.max(list(1, 5))  # \u003c-- will return 5.\nMath.max(list(1, 2), 5)  # \u003c-- will return NaN - can't mix numeric and list arguments.\n```\n\n#### pow (x, y)\n\nDo power between two numbers (equivalent to the ```**``` operator).\n\nFor example:\n\n```Python\nMath.pow(3, 2)  # \u003c-- will return 9, equivalent to '3 ** 2'\n```\n\n#### round (val)\n\nRound a numeric value to its closest round number.\n\nFor example:\n\n```Python\nMath.round(5.2)  # \u003c-- will return 5.\nMath.round(5.6)  # \u003c-- will return 6.\n```\n\n#### floor (val)\n\nRound *down* a numeric value.\n\nFor example:\n\n```Python\nMath.round(5.2)  # \u003c-- will return 5.\nMath.round(5.6)  # \u003c-- will also return 5.\n```\n\n#### ceil (val)\n\nRound *up* a numeric value.\n\nFor example:\n\n```Python\nMath.round(5.2)  # \u003c-- will return 6.\nMath.round(5.6)  # \u003c-- will also return 6.\n```\n\n#### cos (val)\n\nCalculate cos on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Cos of 1: \", Math.cos(1))\n```\n\n#### sin (val)\n\nCalculate sin on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Sin of 1: \", Math.sin(1))\n```\n\n#### atan (val)\n\nCalculate atan on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Atan of 1: \", Math.atan(1))\n```\n\n#### exp (val)\n\nCalculate exp on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Exp of 1: \", Math.exp(1))\n```\n\n#### tan (val)\n\nCalculate tan on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Tan of 1: \", Math.tan(1))\n```\n\n#### log (val)\n\nCalculate log on a numeric value.\n\nFor example:\n\n```Python\nprint(\"Log of 1: \", Math.log(1))\n```\n\n#### sqrt (val)\n\nSquare root a numeric value.\n\nFor example:\n\n```Python\nprint(\"Square root of 4: \", Math.sqrt(4))\n```\n\n#### sign (val)\n\nReturn 1 for positive values, -1 for negatives, 0 for 0.\n\nFor example:\n\n```Python\nMath.sign(4)  # \u003c-- will return 1\nMath.sign(-3)  # \u003c-- will return -1\nMath.sign(0)  # \u003c-- will return 0\n```\n\n#### sum (...)\n\nGet a list of numeric arguments (or a single list argument) and return the sum of the values.\n\nFor example:\n\n```Python\nMath.sum(1,2,3)  # \u003c-- will return 1+2+3 = 6\nMath.sum(list(1,2,3))  # \u003c-- will return 1+2+3 = 6\n```\n\n#### mul (...)\n\nGet a list of numeric arguments (or a single list argument) and return the multiplication of the values.\n\nFor example:\n\n```Python\nMath.mul(2,2,3)  # \u003c-- will return 2*2*3 = 12\nMath.mul(list(2,2,3))  # \u003c-- will return 2*2*3 = 12\n```\n\n#### E\n\nE constant.\n\n#### PI\n\nPI constant.\n\n#### SQRT2\n\nSQRT2 constant.\n\n### Random\n\nProvide random-generation functionality.\n\nThe Random module provide the following API:\n\n#### rand ()\n\nReturn a random float number between 0 and 1.\n\nFor example:\n\n```Python\nprint(Random.rand())\n```\n\n#### rand_int ([min,] max)\n\nReturn a random int number between min and max.\n\nFor example:\n\n```Python\nprint(Random.rand_int(2, 10)) # print a random number between 2 to 10 (inclusive)\nprint(Random.rand_int(5)) # print a random number between 0 to 5 (inclusive)\n```\n\n#### rand_float ([min,] max)\n\nReturn a random float number between min and max.\n\nFor example:\n\n```Python\nprint(Random.rand_float(2, 10)) # print a random number between 2.0 to 10.0 (inclusive)\nprint(Random.rand_float(5)) # print a random number between 0.0 to 5.0 (inclusive)\n```\n\n#### select (iterable)\n\nReturn a random value from a list or a set (doesn't work with dictionaries).\n\nFor example:\n\n```Python\nprint(Random.select(list(1,2,3,4,5))) # get a random value from list options\nprint(Random.select(set(1,2,3,4,5))) # get a random value from set options\n```\n\n#### boolean ()\n\nReturn either ```True``` or ```False```.\n\nFor example:\n\n```Python\nprint(\"And the answer is: \" + Random.boolean())\n```\n\n#### binary ()\n\nReturn either ```0``` or ```1```.\n\nFor example:\n\n```Python\nprint(\"0 or 1: \" + Random.binary())\n```\n\n\n### Alert\n\nProvide functionality to show alerts to user (in browser). Use it for debug purposes, not recommended for production.\n\nThe Alert module provide the following API:\n\n#### alert (msg)\n\nShow a standard browser alert box with msg string.\n\n\n### Input\n\nProvide functionality to get input from user (in browser). Use it for debug purposes, not recommended for production.\n\nThe Input module provide the following API:\n\n#### rawInput (msg, [default])\n\nShow a standard browser prompt box with msg string, and a default value (if provided).\n\n\n# What Next\n\nIf you want to start using Adder Scripts it is recommended you get familiar with the language.\nCheck out the [Adder Sandbox](http://adderscript.com/examples/sandbox.html) and the examples there, or take a look at the following [Cool Game](http://adderscript.com/examples/BotWars/BotWars.html) made with Adder.\n\nIf you find any bugs, problems or security breaches in Adder, please report in the git repository, or drop me an email at ronenness@gmail.com.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fronenness%2Fadder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fronenness%2Fadder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fronenness%2Fadder/lists"}