aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-08-29 18:44:55 +0100
committerLouis Pilfold <louis@lpil.uk>2021-08-29 18:44:55 +0100
commite57c18156cf11aaeae89e66828811c9fcc42fa81 (patch)
tree4a5ceb7226481ed676f39e325bb359bcf98482ea
parent30e5e540ab4edf6582ae77f9440044e22d6d197e (diff)
downloadjavascript-e57c18156cf11aaeae89e66828811c9fcc42fa81.tar.gz
javascript-e57c18156cf11aaeae89e66828811c9fcc42fa81.zip
Mutable references
-rw-r--r--CHANGELOG.md3
-rw-r--r--README.md2
-rw-r--r--src/ffi.js20
-rw-r--r--src/gleam/javascript.gleam18
-rw-r--r--test/gleam/javascript_test.gleam8
5 files changed, 50 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ce8036..be86f89 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,8 @@
## Unreleased
- The `javascript` module was created with the `TypeOf`, and `Symbol` types, and
- `find_symbol`, and `type_of` functions.
+ `find_symbol`, `make_reference`, `set_reference`, `update_reference`,
+ `dereference` and `type_of` functions.
- The `javascript/array` module was created with the `Array(element)` type and
`to_list`, `from_list`, `map`, `fold`, `fold_right`, `get`, and `length`
functions.
diff --git a/README.md b/README.md
index 1875e5c..bdd1887 100644
--- a/README.md
+++ b/README.md
@@ -5,5 +5,7 @@ Extra code for when running on JavaScript
## Features
- Arrays
+- Mutable references
+- Promises
- Symbols
- `typeof`
diff --git a/src/ffi.js b/src/ffi.js
index d3ee8ce..d7b6bf9 100644
--- a/src/ffi.js
+++ b/src/ffi.js
@@ -98,3 +98,23 @@ export function map_promise(promise, fn) {
export function rescue(promise, fn) {
return promise.catch((error) => fn(error));
}
+
+class Reference {
+ constructor(value) {
+ this.value = value;
+ }
+}
+
+export function dereference(reference) {
+ return reference.value;
+}
+
+export function make_reference(value) {
+ return new Reference(value);
+}
+
+export function set_reference(ref, value) {
+ let previous = ref.value;
+ ref.value = value;
+ return previous;
+}
diff --git a/src/gleam/javascript.gleam b/src/gleam/javascript.gleam
index 590dece..f4af2ed 100644
--- a/src/gleam/javascript.gleam
+++ b/src/gleam/javascript.gleam
@@ -17,3 +17,21 @@ pub external fn type_of(value) -> TypeOf =
pub external fn get_symbol(String) -> Symbol =
"../ffi.js" "get_symbol"
+
+pub external type Reference(value)
+
+pub external fn dereference(Reference(a)) -> a =
+ "../ffi.js" "dereference"
+
+pub external fn set_reference(Reference(a), a) -> a =
+ "../ffi.js" "set_reference"
+
+pub external fn make_reference(a) -> Reference(a) =
+ "../ffi.js" "make_reference"
+
+// returns the old value
+pub fn update_reference(ref: Reference(a), f: fn(a) -> a) -> a {
+ let value = dereference(ref)
+ set_reference(ref, f(value))
+ value
+}
diff --git a/test/gleam/javascript_test.gleam b/test/gleam/javascript_test.gleam
index 81477d8..4b0fc9e 100644
--- a/test/gleam/javascript_test.gleam
+++ b/test/gleam/javascript_test.gleam
@@ -23,3 +23,11 @@ pub fn find_symbol_test() {
assert True = javascript.get_symbol("Gleam") == javascript.get_symbol("Gleam")
assert False = javascript.get_symbol("Gleam") == javascript.get_symbol("Lua")
}
+
+pub fn reference_test() {
+ let ref = javascript.make_reference(1)
+ assert 1 = javascript.update_reference(ref, fn(a) { a + 1 })
+ assert 2 = javascript.dereference(ref)
+ assert 2 = javascript.set_reference(ref, 3)
+ assert 3 = javascript.dereference(ref)
+}