aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2024-04-05 20:17:44 +0000
committerBobby <[email protected]>2024-04-05 20:17:44 +0000
commite7b7baba5e6485ae6e241eee4c3f30557afa0fa8 (patch)
treef09be89602cefd9e2dc5102a6e11622753619c7a
parent77d0ea46b3f1de99357c7706c4c05eb44c237412 (diff)
downloadmana-e7b7baba5e6485ae6e241eee4c3f30557afa0fa8.tar.xz
mana-e7b7baba5e6485ae6e241eee4c3f30557afa0fa8.zip
Added Built In Functions for Arrays
-rw-r--r--README.md86
-rw-r--r--evaluator/builtins.go88
2 files changed, 170 insertions, 4 deletions
diff --git a/README.md b/README.md
index fcc80f8..7d79c8f 100644
--- a/README.md
+++ b/README.md
@@ -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}
+ },
+ },
}