{"id":13593263,"url":"https://github.com/skx/monkey","last_synced_at":"2025-04-05T22:06:33.756Z","repository":{"id":39898273,"uuid":"137827908","full_name":"skx/monkey","owner":"skx","description":"An interpreted language written in Go","archived":false,"fork":false,"pushed_at":"2023-12-07T15:00:11.000Z","size":764,"stargazers_count":290,"open_issues_count":2,"forks_count":29,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-29T20:09:55.544Z","etag":null,"topics":["golang","intepreter","monkey","monkey-programming-language"],"latest_commit_sha":null,"homepage":"","language":"Go","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/skx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"skx","custom":"https://steve.fi/donate/"}},"created_at":"2018-06-19T02:04:21.000Z","updated_at":"2025-03-11T18:03:28.000Z","dependencies_parsed_at":"2023-11-17T12:29:21.708Z","dependency_job_id":"36d3d155-fee6-43f7-8b5c-d717924011cd","html_url":"https://github.com/skx/monkey","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fmonkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fmonkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fmonkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fmonkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skx","download_url":"https://codeload.github.com/skx/monkey/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247406088,"owners_count":20933803,"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":["golang","intepreter","monkey","monkey-programming-language"],"created_at":"2024-08-01T16:01:18.522Z","updated_at":"2025-04-05T22:06:33.738Z","avatar_url":"https://github.com/skx.png","language":"Go","readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/skx/monkey)](https://goreportcard.com/report/github.com/skx/monkey)\n[![license](https://img.shields.io/github/license/skx/monkey.svg)](https://github.com/skx/monkey/blob/master/LICENSE)\n[![Release](https://img.shields.io/github/release/skx/monkey.svg)](https://github.com/skx/monkey/releases/latest)\n\n\n\n* [Monkey](#monkey)\n  * [My changes](#my-changes)\n  * [See also](#see-also)\n* [1. Installation](#1-installation)\n  * [Binary Releases](#binary-releases)\n* [1.1 Usage](#11-usage)\n* [2 Syntax](#2-syntax)\n  * [2.1 Definitions](#21-definitions)\n  * [2.2 Arithmetic operations](#22-arithmetic-operations)\n  * [2.3 Builtin containers](#23-builtin-containers)\n    * [2.3.1 Arrays](#231-arrays)\n    * [2.3.2 Hashes](#232-hashes)\n  * [2.4 Builtin functions](#24-builtin-functions)\n    * [2.4.1 The Standard Library](#241-the-standard-library)\n  * [2.5 Functions](#25-functions)\n  * [2.6 If-else statements](#26-if-else-statements)\n    * [2.6.1 Ternary expressions](#261-ternary-expressions)\n  * [2.7 Switch statements](#27-switch-statements)\n  * [2.8 For-loop statements](#28-for-loop-statements)\n    * [2.8.1 Foreach statements](#281-foreach-statements)\n  * [2.9 Comments](#29-comments)\n  * [2.10 Postfix Operators](#29-postfix-operators)\n  * [2.11 Command Execution](#211-command-execution)\n  * [2.12 Regular Expressions](#212-regular-expressions)\n  * [2.13 File I/O](#213-file-io)\n  * [2.14 File Operations](#214-file-operations)\n  * [3. Object Methods](#3-object-methods)\n      * [3.1 Defininig New Object Methods](#31-defininig-new-object-methods)\n* [Github Setup](#github-setup)\n* [Fuzz Testing](#fuzz-testing)\n\n\n\n\n# Monkey\n\nThis repository contains an interpreter for the \"Monkey\" programming language, as described in [Write an Interpreter in Go](https://interpreterbook.com).\n\n#### My changes\n\nThe interpreter in _this_ repository has been significantly extended from the starting point:\n\n* Added single-line \u0026 multi-line comments.\n* Added postfix operators (`i++`, `i--`).\n* Allow accessing individual characters of a string via the index-operator.\n* Added a driver to read from STDIN, or a named file, rather than a REPL.\n    * This allows executing the examples easily (for example \"`./monkey examples/hello.mon`\".)\n* Added a collection of standard-library functions.\n    * Including file input/output, type-discovery, string, and math functions.\n* Added a new way to define functions, via `function`.\n* Added the general-purpose comparision functions `\u003c=` \u0026 `\u003e=`.\n* Allow string comparisons via `==`, `!=`, `\u003c=`, \u0026 `\u003e=`.\n* Allow comparisions to be complex:\n  * `if ( a \u003e= 'a' \u0026\u0026 a \u003c= 'z' ) ..`\n  * `if ( a || b ) ..`\n* Allow assignments without `let`.\n    * This also allows operators such as \"`+=`\", \"`-=`\", \"`*=`\", \u0026 \"`/=`\" to work.\n* Added command-line handling, so that scripts can read their own arguments.\n* Added global-constants available by default\n    * For example `PI`, `E`, `STDIN`, `STDOUT`, \u0026 `STDERR`.\n* Most scripts will continue running in the face of errors.\n    * To correct/detect \"obvious\" errors add `pragma(\"strict\");` to your script, which will cause the interpreter to show a suitable error-message and terminate.\n* Function arguments may have defaults.  For example:\n  * `function greet( name = \"World\" ) { puts(\"Hello, \" + name + \"\\n\"); }`\n* Moved parts of the standard-library to 100% pure monkey, rather than implementing it in go.\n  * See [data/stdlib.mon](data/stdlib.mon) for the implementation.\n  * See also the notes on [object-based methods](#31-defininig-new-object-methods).\n* Added the `eval` function.\n  * Which allows executing monkey-code from a string.\n* Improved error-reporting from the parser.\n  * It will now show the line-number of failures (where possible).\n* Added support for regular expressions, both literally and via `match`\n  * `if ( name ~= /steve/i ) { puts( \"Hello Steve\\n\"); } `\n* Added support for [ternary expressions](#261-ternary-expressions).\n* Added support for creating arrays of consecutive integers via the range operator (`1..10`).\n* Added the ability to iterate over the contents of arrays, hashes, and strings via the `foreach` statement.\n* Added `printf` and `sprintf` primitives, which work as you would expect.\n  * `printf( \"%d %s\", 3, \"Steve\" );`\n* Added support for `switch` statements, with block-based `case` expressions.\n  * No bugs due to C-style \"fall-through\".\n* Add support for explicit `null` usage:\n  * `a = null;  if ( a == null ) { .. }`\n\n#### See Also\n\nIf you enjoyed this repository you might find the related ones interesting:\n\n* A tutorial-lead approach to implementing a FORTH interpreter:\n  * https://github.com/skx/foth\n* A simple TCL-like interpreter:\n  * https://github.com/skx/critical\n* A BASIC interpreter:\n  * https://github.com/skx/gobasic\n* An embedded scripting language, based upon the same Monkey core\n  * This follows the second book, but large parts of the code were replaced with different implementations, and things were extended a lot.\n  * https://github.com/skx/evalfilter\n\nFinally I put together a couple of \"complex\" compilers, which convert input into AMD64 assembly language:\n\n* A mathematical compiler\n  * https://github.com/skx/math-compiler\n* A brainfuck compiler:\n  * https://github.com/skx/bfcc\n\n\n\n## 1. Installation\n\nDue to the embedded [standard-library implementation](data/stdlib.mon), which is implemented in monkey, you'll need to compile this project with go version 1.16beta1 or higher.\n\nYou can install from source like so:\n\n    git clone https://github.com/skx/monkey\n    cd monkey\n    go install\n\n\n### Binary Releases\n\nAlternatively you could install a binary-release, from the [release page](https://github.com/skx/monkey/releases).\n\nIf you're an [emacs](https://www.gnu.org/software/emacs/) user might also wish to install the [monkey.el](emacs/monkey.el) file, which provides syntax highlighting for monkey-scripts.\n\n\n### 1.1 Usage\n\nTo execute a monkey-script simply pass the name to the interpreter:\n\n     $ monkey ./example/hello.mon\n\nScripts can be made executable by adding a suitable shebang line:\n\n     $ cat hello.mon\n     #!/usr/bin/env monkey\n     puts( \"Hello, world!\\n\" );\n\nExecution then works as you would expect:\n\n     $ chmod 755 hello.mon\n     $ ./hello.mon\n     Hello, world!\n\nIf no script-name is passed to the interpreter it will read from STDIN and\nexecute that instead, allowing simple tests to be made.\n\n\n\n\n# 2 Syntax\n\n**NOTE**: Example-programs can be found beneath [examples/](examples/) which\ndemonstrate these things, as well as parts of the standard-library.\n\n\n\n## 2.1 Definitions\n\nVariables are defined using the `let` keyword, with each line ending with `;`.\n\n      let a = 3;\n      let b = 1.2;\n\nVariables may be integers, floats, strings, or arrays/hashes (which are discussed later).\n\nSome variables are defined by default, for example:\n\n    puts( PI ); // Outputs: 3.14159..\n    puts( E );  // Outputs: 2.71828..\n\nVariables may be updated without the need for `let`, for example this works\nas you would expect:\n\n    let world = \"Earth\";\n    world = \"world\";\n    puts( \"Hello, \" + world + \"!\\n\");\n\nIf you're __not__ running with `pragma(\"strict\");` you can also declare and\nuse variables without the need for `let`, but that should be avoided as\ntypos will cause much confusion!\n\n     name = \"Steve\";\n     puts( \"Hello, \" + name + \"\\n\");\n\n\n\n## 2.2 Arithmetic operations\n\n`monkey` supports all the basic arithmetic operation of `int` and `float` types.\n\nThe `int` type is represented by `int64` and `float` type is represented by `float64`.\n\n\n       let a = 3;\n       let b = 1.2;\n\n       puts( a + b  );  // Outputs: 4.2\n       puts( a - b  );  // Outputs: 1.8\n       puts( a * b  );  // Outputs: 3.6\n       puts( a / b  );  // Outputs: 2.5\n       puts( 2 ** 3 ) ; // Outputs: 8\n\nHere `**` is used to raise the first number to the power of the second.\nWhen operating with integers the modulus operator is available too, via `%`.\n\n\n\n## 2.3 Builtin containers\n\n`monkey` contains two builtin containers: `array` and `hash`.\n\n\n### 2.3.1 Arrays\n\nAn array is a list which organizes items by linear sequence.  Arrays can hold multiple types.\n\n     let a = [1, 2.3, \"array\"];\n     let b = [false, true, \"Hello World\", 3, 3.13];\n\n\nAdding to an array is done via the `push` function:\n\n     let a = push(a, \"another\");\n\nYou can iterate over the contents of an array like so:\n\n     let i = 0;\n     for( i \u003c len(a) ) {\n        puts( \"Array index \", i, \" contains \", a[i], \"\\n\");\n        i++\n     }\n\nWith the definition we included that produces this output:\n\n     Array index 0 contains 1\n     Array index 1 contains 2.3\n     Array index 2 contains array\n     Array index 3 contains another\n\nAs a helper you may define an array of consecutive integers via the range operator (`..`):\n\n     let a = 1..10;\n\n\n### 2.3.2 Hashes\n\nA hash is a key/value container, but note that keys may only be of type `boolean`, `int` and `string`.\n\n\n    let a = {\"name\":\"monkey\",\n             true:1,\n             7:\"seven\"};\n\n    puts(a); // Outputs: {name: monkey, true: 1, 7: seven}\n\n    puts(a[\"name\"]); // Outputs: monkey\n\nUpdating a hash is done via the `set` function, but note that this returns\nan updated hash - rather than changing in-place:\n\n    let b = set(a, 8, \"eight\");\n    puts(b);  // Outputs: {name: monkey, true: 1, 7: seven, 8: eight}\n\nYou can iterate over the keys in a hash via the `keys` function, or delete\nkeys via `delete` (again these functions returns an updated value rather than\nchanging it in-place).\n\nHash functions are demonstrated in the [examples/hash.mon](examples/hash.mon) sample.\n\n\n\n## 2.4 Builtin functions\n\nThe core primitives are:\n\n* `delete`\n  * Deletes a hash-key.\n* `int`\n  * convert the given float/string to an integer.\n* `keys`\n  * Return the keys of the specified array.\n* `len`\n  * Yield the length of builtin containers.\n* `match`\n  * Regular-expression matching.\n* `pragma`\n  * Allow the run-time environment to be controlled.\n  * We currently support only `pragma(\"strict\");`.\n* `push`\n  * push an elements into the array.\n* `puts`\n  * Write literal value of objects to STDOUT.\n* `printf`\n  * Write values to STDOUT, via a format-string.\n* `set`\n  * insert key value pair into the map.\n* `sprintf`\n  * Create strings, via a format-string.\n* `string`\n  * convert the given item to a string.\n* `type`\n  * returns the type of a variable.\n\nThe following functions are also part of our standard library, but are\nimplemented in 100% pure monkey:\n\n* `first`\n  * yield the first element of array.\n* `last`\n  * yield the last element of array.\n* `rest`\n  * yield an array which excludes the first element.\n\n\n\n## 2.4.1 The Standard Library\n\nIn addition to the core built-in functions we also have a minimal-standard library.  The library includes some string/file primitives, a regular-expression matcher, and some maths-helpers.\n\nYou can see the implementation of the go-based standard-library beneath [evaluator/stdlib*](evaluator/), and several of these functions are documented in the various [examples/](examples/).\n\n**NOTE**: Parts of our standard-library are implemented in 100% pure monkey,\nand these are embedded in our compiled interpreter.  The source of the functions\ncan be viewed in [data/stdlib.mon](data/stdlib.mon).\n\nIf you wish to make changes to the monkey-based standard-library you'll\nneed to rebuild the interpreter after making your changes, to ensure they are bundled into the executable.\n\nNothing special is required, the following will suffice as you'd expect:\n\n    go build .\n\n\n\n## 2.5 Functions\n\n`monkey` uses `fn` to define a function which will be assigned to a variable for\nnaming/invocation purposes:\n\n\n    let add = fn(a, b) { return a + b;};\n    puts(add(1,2));  // Outputs: 3\n\n    // functions can be used via their variables\n    let addTwo = fn(a,b, f) { return 2 + f(a, b);};\n    puts( addTwo(1,2, add) ); // outputs: 5.\n\nIt is also possible to define a function without the use of `let`, via the `function` keyword.  This was added to make the language feel more natural to C-developers:\n\n    function hello() { puts \"Hello, world\\n\" ; };\n    hello();   // Outputs: Hello, world\" to the console.\n\nYou may specify a default value for arguments which are not provided, for example:\n\n    let foo = fn( name = \"World!\") {\n      puts( \"Hello, \" + name + \"\\n\" );\n    };\n\n    foo();\n    foo( \"Steve\" );\n\nThis will output what you expect:\n\n    Hello, World!\n    Hello, Steve\n\nThe same thing works for literal functions:\n\n    // Function with a default (string) argument\n    function meh( arg = \"Steve\" ) {\n      puts( \"Argument:\", arg, \" has type:\", type(arg), \"\\n\");\n    };\n\n    // Call it with no argument and the default will be used.\n    meh();\n\n    // But of course all the rest work just fine.\n    meh( 1 );\n    meh( 1/3.0 );\n    meh( \"Steve\" );\n    meh( [1,2,3,4] );\n    meh( {\"Steve\":\"Kemp\", true:1, false:0, 7:\"seven\"} );\n\n\n\n## 2.6 If-else statements\n\n`monkey` supports if-else statements.\n\n    let max = fn(a, b) {\n      if (a \u003e b) {\n        return a;\n      } else {\n        return b;\n        }\n    };\n\n    puts( max(1, 2) );  // Outputs: 2\n\n\n### 2.6.1 Ternary Expressions\n\n`monkey` supports the use of ternary expressions, which work as you\nwould expect with a C-background:\n\n    function max(a,b) {\n      return( a \u003e b ? a : b );\n    };\n\n    puts( \"max(1,2) -\u003e \", max(1, 2), \"\\n\" );\n    puts( \"max(-1,-2) -\u003e \", max(-1, -2), \"\\n\" );\n\nNote that in the interests of clarity nested ternary-expressions are illegal!\n\n\n\n## 2.7 Switch Statements\n\nMonkey supports the `switch` and `case` expressions, as the following example demonstrates:\n\n```\n  name = \"Steve\";\n\n  switch( name ) {\n    case /^steve$/i {\n       printf(\"Hello Steve - we matched you via a regexp\\n\");\n    }\n    case \"St\" + \"even\" {\n       printf(\"Hello SteveN, you were matched via an expression\\n\" );\n    }\n    case 3 {\n       printf(\"Hello number three, we matched you literally.\\n\");\n    }\n    default {\n       printf(\"Default case: %s\\n\", string(name) );\n    }\n  }\n```\n\nSee also [examples/switch.mon](examples/switch.mon).\n\n\n\n## 2.8 For-loop statements\n\n`monkey` supports a golang-style for-loop statement.\n\n     let sum = fn(x) {\n        let i = 1;\n        let sum = 0;\n\n        for (i \u003c x) {\n           sum += i;\n           i++;\n        }\n        return sum;\n     };\n\n     puts(sum(100));  // Outputs: 4950\n\n\n\n## 2.8.1 Foreach statements\n\nIn addition to iterating over items with the `for` statement, as shown above, it is also possible to iterate over various items via the `foreach` statement.\n\nFor example to iterate over an array:\n\n     a = [ \"My\", \"name\", \"is\", \"Steve\" ]\n     foreach item in a {\n          puts( \"\\t\",  item , \"\\n\");\n     }\n\nHere you see that we've iterated over the items of the array, we can also see their offsets like so:\n\n     foreach offset, item in a {\n          puts( offset, \"\\t\",  item , \"\\n\");\n     }\n\nThe same style of iteration works for Arrays, Hashes, and the characters which make up a string.  You can see examples of this support in [examples/iteration.mon](examples/iteration.mon).\n\nWhen iterating over hashes you can receive either the keys, or the keys and value at each step in the iteration, otherwise you receive the value and an optional index.\n\n\n\n## 2.9 Comments\n\n`monkey` support two kinds of comments:\n\n* Single-line comments begin with `//` and last until the end of the line.\n* Multiline comments between `/*` and `*/`.\n\n\n\n## 2.10 Postfix Operators\n\nThe `++` and `--` modifiers are permitted for integer-variables, for example the following works as you would expect showing the numbers from `0` to `5`:\n\n    let i = 0;\n    for ( i \u003c= 5 ) {\n       puts( i, \"\\n\" );\n       i++;\n    }\n\nAnother feature borrowed from C allows variables to be updated in-place via the operators `+=`, `-=`, `*=`, \u0026 `/=`.\n\nUsing `+=` our previous example could be rewritten as:\n\n    let i = 0;\n    for ( i \u003c= 5 ) {\n       puts( i, \"\\n\" );\n       i += 1;\n    }\n\nThe update-operators work with integers and doubles by default, when it comes to strings the only operator supported is `+=`, allowing for a string-append:\n\n    let str = \"Forename\";\n    str += \" Surname\";\n    str += \"\\n\";\n    puts( str );           // -\u003e \"Forename Surname\\n\"\n\n\n\n## 2.11 Command Execution\n\nAs with many scripting languages commands may be executed via the backtick\noperator (``).\n\n      let uptime = `/usr/bin/uptime`;\n\n      if ( uptime[\"exitCode\"] == 0 ) {\n          puts( \"STDOUT: \", uptime[\"stdout\"].trim() , \"\\n\");\n      } else {\n          puts( \"An error occurred while running the command: \", uptime[\"stderr\"].trim(), \"\\n\");\n      }\n\nThe output will be a hash containing the keys `stdout`, `stderr`, and `exitCode`, as demonstrated in [examples/exec.mon](examples/exec.mon).\n\n\n\n## 2.12 Regular Expressions\n\nThe `match` function allows matching a string against a regular-expression.\n\nIf a match fails NULL will be returned, otherwise a hash containing any\ncapture groups in the match.\n\nThis is demonstrated in the [examples/regexp.mon](examples/regexp.mon) example.\n\nYou can also perform matching (complete with captures), with a literal regular expression object:\n\n    if ( Name ~= /steve/i ) { puts( \"Hello Steve\\n\" ); }\n    if ( Name !~ /[aeiou]/i ) { puts( \"You have no vowels.\\n\" ); }\n\n    // captures become $1, $2, $N, etc.\n    ip = \"192.168.1.1\";\n    if ( ip ~= /([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)/  ) {\n        printf(\"Matched! %s.%s.%s.%s\\n\", $1, $2, $3, $4 );\n    }\n\n\n\n## 2.13 File I/O\n\nThe `open` primitive is used to open files, and can be used to open files for either reading, or writing:\n\n    // Open a file for reading\n    fh = open( \"/etc/passwd\" );\n    fh = open( \"/etc/passwd\", \"r\" );\n\n    // Open a file for writing\n    fh = open( \"/tmp/blah\", \"w\" );\n\n    // Open a file for appending\n    fh = open( \"/tmp/blah\", \"wa\" );\n\nOnce you have a file-object you can invoke methods upon it:\n\n* `read()`\n  * Read a line of input, returning that input as a string.\n* `readlines()`\n  * Read the lines of the given file, and return them as an array.\n* `write(data)`\n  * Write the data to the given file.\n\nThese are demonstrated in the following examples:\n\n* [examples/file.mon](examples/file.mon)\n  * Simple example.\n* [examples/file-writing.mon](examples/file-writing.mon)\n  * Simple example.\n* [examples/wc.mon](examples/wc.mon)\n* [examples/wc2.mon](examples/wc2.mon)\n  * Counting lines.\n\nBy default three filehandles will be made available, as constants:\n\n* `STDIN`\n  * Use for reading STDIN.\n* `STDOUT`\n* `STDERR`\n  * Used for writing messages.\n\n\n\n## 2.14 File Operations\n\nThe primitive `stat` will return a hash of details about the given file, or\ndirectory entry.\n\nYou can change the permissions of a file via the `chmod` function, but note that the second argument is an __octal__ string:\n\n    chmod( \"/tmp/evil.sh\", \"755\")\n    chmod( \"/tmp/normal\", \"644\")\n\nTo remove a file, use `unlink`:\n\n    unlink( \"/tmp/trash.txt\" )\n\nAnd finally to make a directory:\n\n    mkdir( \"/tmp/blah\" );\n\n\n\n\n# 3. Object Methods\n\nThere is now support for \"object-methods\".  Object methods are methods\nwhich are defined against a _type_.  For example all of our primitive\ntypes allow a `methods()` method, which returns the methods which are\navailable against them.\n\nSimilarly each of them implement a `type()` function which returns the\ntype involved:\n\n    let i = 1;\n    puts( i.type() );\n\n    let s = \"Steve\";\n    puts( s.type() );\n\nOr even:\n\n    puts( \"Steve\".type() );\n\nSeeing methods available works as you would expect:\n\n    a = [ \"Array\", \"Is\", \"Here\" ];\n\n    let i = 0;\n    for ( i \u003c len(a.methods() ) ) {\n       puts( \"Method \" + a.methods()[i] + \"\\n\" );\n       i++;\n    }\n\nThis shows:\n\n    Method find\n    Method len\n    Method methods\n    Method string\n\nThe `string` object has the most methods at the time of writing, but\nno doubt things will change over time.\n\n\n\n## 3.1 Defininig New Object Methods\n\nThe object-methods mentioned above are implemented in Go, however it is also\npossible to define such methods in 100% monkey!\n\nYou can define a method via something like:\n\n    function string.steve() {\n       puts( \"Hello, I received '\", self, \"' as an argument\\n\" );\n    }\n\nNote that the function has access to the object it was invoked upon via the\nimplicit `self` name.  Invocation would look as you expect:\n\n    let s = \"Hello, world\";\n    s.steve();   -\u003e Hello, I received 'Hello, world' as an argument\n\nYou can see [data/stdlib.mon](data/stdlib.mon) implements some primitives\nin this fashion, for example the functional-programming methods `array.map`,\n`array.filter`, `string.toupper`, etc, etc.\n\n\n\n## Github Setup\n\nThis repository is configured to run tests upon every commit, and when\npull-requests are created/updated.  The testing is carried out via\n[.github/run-tests.sh](.github/run-tests.sh) which is used by the\n[github-action-tester](https://github.com/skx/github-action-tester) action.\n\nReleases are automated in a similar fashion via [.github/build](.github/build),\nand the [github-action-publish-binaries](https://github.com/skx/github-action-publish-binaries) action.\n\n\n\n## Fuzz Testing\n\nFuzz-testing involves creating random input, and running the program to test with that, to see what happens.\n\nThe intention is that most of the random inputs will be invalid, so you'll be able to test your error-handling and see where you failed to consider specific input things.\n\nThe 1.18 release of the golang compiler/toolset has integrated support for fuzz-testing, and you can launch it like so:\n\n```sh\ngo test -fuzztime=300s -parallel=1 -fuzz=FuzzMonkey -v\n```\n\nSample output looks like this:\n\n```\n$ go test -fuzztime=300s -parallel=1 -fuzz=FuzzMonkey -v\n=== RUN   FuzzMonkey\nfuzz: elapsed: 0s, gathering baseline coverage: 0/240 completed\nfuzz: elapsed: 0s, gathering baseline coverage: 240/240 completed, now fuzzing with 1 workers\nfuzz: elapsed: 3s, execs: 4321 (1440/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 6s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\ncfuzz: elapsed: 9s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 12s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 15s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 18s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 21s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 24s, execs: 4321 (0/sec), new interesting: 6 (total: 246)\nfuzz: elapsed: 27s, execs: 73463 (23060/sec), new interesting: 17 (total: 257)\nfuzz: elapsed: 30s, execs: 75639 (725/sec), new interesting: 18 (total: 258)\nfuzz: elapsed: 33s, execs: 125712 (16701/sec), new interesting: 25 (total: 265)\nfuzz: elapsed: 36s, execs: 139338 (4543/sec), new interesting: 34 (total: 274)\nfuzz: elapsed: 39s, execs: 173881 (11511/sec), new interesting: 49 (total: 289)\nfuzz: elapsed: 42s, execs: 198046 (8055/sec), new interesting: 55 (total: 295)\nfuzz: elapsed: 45s, execs: 210203 (4054/sec), new interesting: 75 (total: 315)\nfuzz: elapsed: 48s, execs: 262945 (17580/sec), new interesting: 85 (total: 325)\nfuzz: elapsed: 51s, execs: 297505 (11517/sec), new interesting: 108 (total: 348)\nfuzz: elapsed: 54s, execs: 308672 (3722/sec), new interesting: 116 (total: 356)\nfuzz: elapsed: 57s, execs: 341614 (10984/sec), new interesting: 123 (total: 363)\nfuzz: elapsed: 1m0s, execs: 366053 (8146/sec), new interesting: 131 (total: 371)\nfuzz: elapsed: 1m3s, execs: 396575 (10172/sec), new interesting: 137 (total: 377\n...\n```\n\nSteve\n--\n","funding_links":["https://github.com/sponsors/skx","https://steve.fi/donate/"],"categories":["开源类库","Go","Open source library"],"sub_categories":["解释器","Interpreter"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fmonkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskx%2Fmonkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fmonkey/lists"}