diff options
| author | Bobby <[email protected]> | 2024-04-05 20:17:44 +0000 |
|---|---|---|
| committer | Bobby <[email protected]> | 2024-04-05 20:17:44 +0000 |
| commit | e7b7baba5e6485ae6e241eee4c3f30557afa0fa8 (patch) | |
| tree | f09be89602cefd9e2dc5102a6e11622753619c7a | |
| parent | 77d0ea46b3f1de99357c7706c4c05eb44c237412 (diff) | |
| download | mana-e7b7baba5e6485ae6e241eee4c3f30557afa0fa8.tar.xz mana-e7b7baba5e6485ae6e241eee4c3f30557afa0fa8.zip | |
Added Built In Functions for Arrays
| -rw-r--r-- | README.md | 86 | ||||
| -rw-r--r-- | evaluator/builtins.go | 88 |
2 files changed, 170 insertions, 4 deletions
@@ -137,9 +137,13 @@ fn add(x, y) { Mana has a number of built-in functions that are available to the programmer. These functions are built into the language and can be used without having to define them. The following is a list of built-in functions that are available in Mana: -| Function | Description | Parameters | Example | -| -------- | ------------------------------ | ---------- | ---------------------- | -| `len` | Returns the length of a string | `string` | `len("Hello, World!")` | +| Function | Description | Parameters | Example | Output | +| -------- | --------------------------------------------- | --------------------- | ---------------------- | -------------- | +| `len` | Returns the length of a string or an array | `string` | `len("Hello, World!")` | `13` | +| `push` | Appends an element to the end of an array | `array`, `expression` | `push([1, 2, 3], 4)` | `[1, 2, 3, 4]` | +| `first` | Returns the first element of an array | `array` | `first([1, 2, 3])` | `1` | +| `last` | Returns the last element of an array | `array` | `last([1, 2, 3])` | `3` | +| `rest` | Returns all but the first element of an array | `array` | `rest([1, 2, 3])` | `[2, 3]` | ## Strings @@ -169,11 +173,85 @@ let c = 69; let f = mixed[3](5); // f = 25 -let u = ["one", "two", 3][5 - 4]; // s = "two" +let u = ["one", "two", 3][5 - 4]; // u = "two" let k = mixed[c - 67]; // k = true ``` +## Building Advanced Functions + +**Map** + +```rust +let map = fn(arr, f) { + let iter = fn(arr, accumulated) { + if (len(arr) == 0) { + accumulated + } else { + iter(rest(arr), push(accumulated, f(first(arr)))); + } + }; + + iter(arr, []); +}; + +let a = [1, 2, 3, 4, 5]; +let double = fn(x) { x * 2; }; + +let doubled = map(a, double); // doubled = [2, 4, 6, 8, 10] +``` + +**Reduce** + +```rust +let reduce = fn(arr, initial, f) { + let iter = fn(arr, result) { + if (len(arr) == 0) { + result + } else { + iter(rest(arr), f(result, first(arr))); + } + }; + + iter(arr, initial); +}; + +let a = [1, 2, 3, 4, 5]; + +let sum = fn(arr) { + reduce(arr, 0, fn(initial, el) { initial + el; }); +}; + +sum(a); // sum = 15 +``` + +**Filter** + +```rust +let filter = fn(arr, f) { + let iter = fn(arr, filtered) { + if (len(arr) == 0) { + filtered + } else { + let x = first(arr); + if (f(x)) { + iter(rest(arr), push(filtered, x)); + } else { + iter(rest(arr), filtered); + } + } + }; + + iter(arr, []); +}; + +let a = [1, 2, 3, 4, 5]; + +let two = fn(x) { x == 2; }; + +let filtered = filter(a, two); // filtered = [2] +``` + ## Building the Project To build the project, you will need to have Go installed on your machine. You can download Go from the [official website](https://golang.org/). Once you have Go installed, you can build the project by running the following command: diff --git a/evaluator/builtins.go b/evaluator/builtins.go index 0e6846a..1c7a312 100644 --- a/evaluator/builtins.go +++ b/evaluator/builtins.go @@ -15,9 +15,97 @@ var builtins = map[string]*object.Builtin{ switch arg := args[0].(type) { case *object.String: return &object.Integer{Value: int64(len(arg.Value))} + case *object.Array: + return &object.Integer{Value: int64(len(arg.Elements))} default: return newError("argument to `len` not supported, got %s", arg.Type()) } }, }, + "first": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 1 { + return newError("wrong number of arguments. got=%d, want=1", + len(args)) + } + + if args[0].Type() != object.ARRAY_OBJ { + return newError("argument to `first` must be ARRAY, got %s", + args[0].Type()) + } + + arr := args[0].(*object.Array) + if len(arr.Elements) > 0 { + return arr.Elements[0] + } + + return NULL + }, + }, + "last": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 1 { + return newError("wrong number of arguments. got=%d, want=1", + len(args)) + } + + if args[0].Type() != object.ARRAY_OBJ { + return newError("argument to `last` must be ARRAY, got %s", + args[0].Type()) + } + + arr := args[0].(*object.Array) + length := len(arr.Elements) + if length > 0 { + return arr.Elements[length-1] + } + + return NULL + }, + }, + "rest": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 1 { + return newError("wrong number of arguments. got=%d, want=1", + len(args)) + } + + if args[0].Type() != object.ARRAY_OBJ { + return newError("argument to `rest` must be ARRAY, got %s", + args[0].Type()) + } + + arr := args[0].(*object.Array) + length := len(arr.Elements) + if length > 0 { + newElements := make([]object.Object, length-1) + copy(newElements, arr.Elements[1:length]) + return &object.Array{Elements: newElements} + } + + return NULL + }, + }, + "push": { + Fn: func(args ...object.Object) object.Object { + if len(args) != 2 { + return newError("wrong number of arguments. got=%d, want=2", + len(args)) + } + + if args[0].Type() != object.ARRAY_OBJ { + return newError("argument to `push` must be ARRAY, got %s", + args[0].Type()) + } + + arr := args[0].(*object.Array) + length := len(arr.Elements) + + newElements := make([]object.Object, length+1) + copy(newElements, arr.Elements) + newElements[length] = args[1] + + return &object.Array{Elements: newElements} + }, + }, } |
