fusion-lang 0.0.1.alpha1 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +19 -6
- data/Rakefile +9 -0
- data/docs/lang/design.md +418 -28
- data/docs/lang/implementation.md +238 -0
- data/docs/lang/roadmap.md +20 -57
- data/docs/user/explanation.md +5 -10
- data/docs/user/how-to-guides.md +62 -23
- data/docs/user/reference.md +596 -168
- data/docs/user/tutorial.md +32 -29
- data/examples/double.fsn +1 -1
- data/examples/ends.fsn +4 -0
- data/examples/factorial.fsn +2 -2
- data/examples/fizzbuzz.fsn +1 -4
- data/examples/json_test.fsn +4 -0
- data/examples/palindrome.fsn +2 -1
- data/exe/fusion +17 -44
- data/lib/fusion/ast.rb +97 -0
- data/lib/fusion/atom.rb +17 -0
- data/lib/fusion/cli/decoder.rb +84 -0
- data/lib/fusion/cli/encoder.rb +28 -0
- data/lib/fusion/cli/options.rb +212 -0
- data/lib/fusion/cli/parser.rb +38 -0
- data/lib/fusion/cli/repl.rb +78 -0
- data/lib/fusion/cli/serializer.rb +70 -0
- data/lib/fusion/cli.rb +207 -0
- data/lib/fusion/interpreter/builtins.rb +465 -0
- data/lib/fusion/interpreter/env.rb +89 -0
- data/lib/fusion/interpreter/error_val.rb +71 -0
- data/lib/fusion/interpreter/func.rb +22 -0
- data/lib/fusion/interpreter/native_func.rb +22 -0
- data/lib/fusion/interpreter/thunk.rb +53 -0
- data/lib/fusion/interpreter.rb +752 -0
- data/lib/fusion/lexer.rb +249 -0
- data/lib/fusion/null.rb +9 -0
- data/lib/fusion/parser.rb +542 -0
- data/lib/fusion/token.rb +22 -0
- data/lib/fusion/typed_data.rb +23 -0
- data/lib/fusion/version.rb +1 -1
- data/lib/fusion/wire_pair.rb +11 -0
- data/lib/fusion.rb +11 -1122
- data/stdlib/all.fsn +13 -0
- data/stdlib/any.fsn +12 -0
- data/stdlib/chars.fsn +5 -0
- data/stdlib/compact.fsn +6 -0
- data/stdlib/concat.fsn +5 -0
- data/stdlib/falsey.fsn +6 -0
- data/stdlib/filter.fsn +12 -0
- data/stdlib/flatten.fsn +7 -0
- data/stdlib/gt.fsn +9 -0
- data/stdlib/gte.fsn +9 -0
- data/stdlib/lt.fsn +9 -0
- data/stdlib/lte.fsn +9 -0
- data/stdlib/map.fsn +6 -2
- data/stdlib/range.fsn +2 -1
- data/stdlib/reduce.fsn +8 -0
- data/stdlib/sanitize.fsn +12 -0
- data/stdlib/truthy.fsn +7 -0
- metadata +41 -2
- data/stdlib/math/square.fsn +0 -1
data/stdlib/all.fsn
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Return true if every item satisfies the predicate "f" (a truthy result) — over an
|
|
2
|
+
# array's elements or an object's values. Input: {"f": predicate, "c": array-or-object}.
|
|
3
|
+
# Short-circuits: the first item whose predicate is falsey yields false without testing
|
|
4
|
+
# the rest.
|
|
5
|
+
(
|
|
6
|
+
{"f": _ ? @Function, "c": []} => true,
|
|
7
|
+
{"f": f ? @Function, "c": [x, ...rest]} => (x | f) | (
|
|
8
|
+
_ ? @falsey => false,
|
|
9
|
+
_ => {"f": f, "c": rest} | @,
|
|
10
|
+
),
|
|
11
|
+
{"f": f ? @Function, "c": obj ? @Object} => {"f": f, "c": obj | @values} | @,
|
|
12
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@all", "status": 0, "input": x, "expected": ["{\"f\": _ ? @Function, \"c\": _ ? @Array}", "{\"f\": _ ? @Function, \"c\": _ ? @Object}"]},
|
|
13
|
+
)
|
data/stdlib/any.fsn
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# True if any item satisfies the predicate — over an array's elements or an object's
|
|
2
|
+
# values. Input: {"f": predicate, "c": array-or-object}. Short-circuits on the first
|
|
3
|
+
# truthy result.
|
|
4
|
+
(
|
|
5
|
+
{"f": _ ? @Function, "c": []} => false,
|
|
6
|
+
{"f": f ? @Function, "c": [x, ...rest]} => x | f | (
|
|
7
|
+
_ ? @falsey => {"f": f, "c": rest} | @,
|
|
8
|
+
_ => true,
|
|
9
|
+
),
|
|
10
|
+
{"f": f ? @Function, "c": obj ? @Object} => {"f": f, "c": obj | @values} | @,
|
|
11
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@any", "status": 0, "input": x, "expected": ["{\"f\": _ ? @Function, \"c\": _ ? @Array}", "{\"f\": _ ? @Function, \"c\": _ ? @Object}"]},
|
|
12
|
+
)
|
data/stdlib/chars.fsn
ADDED
data/stdlib/compact.fsn
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Drop null entries from an array (by element) or an object (by value). Built on @filter.
|
|
2
|
+
(
|
|
3
|
+
xs ? @Array => {"f": (null => false, _ => true), "c": xs} | @filter,
|
|
4
|
+
obj ? @Object => {"f": (null => false, _ => true), "c": obj} | @filter,
|
|
5
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@compact", "status": 0, "input": x, "expected": ["_ ? @Array", "_ ? @Object"]}
|
|
6
|
+
)
|
data/stdlib/concat.fsn
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Concatenate two strings. Input: [a, b]. Built on @join with an empty separator.
|
|
2
|
+
(
|
|
3
|
+
[a ? @String, b ? @String] => [[a, b], ""] | @join,
|
|
4
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@concat", "status": 0, "input": x, "expected": ["[_ ? @String, _ ? @String]"]}
|
|
5
|
+
)
|
data/stdlib/falsey.fsn
ADDED
data/stdlib/filter.fsn
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Keep the array elements (or object values) for which f(x) is truthy. Input:
|
|
2
|
+
# {"f": predicate, "c": array-or-object}. Like @map, it is polymorphic on c.
|
|
3
|
+
(
|
|
4
|
+
{"f": _ ? @Function, "c": []} => [],
|
|
5
|
+
{"f": f ? @Function, "c": [x, ...rest]} => x | f | (
|
|
6
|
+
_ ? @falsey => {"f": f, "c": rest} | @,
|
|
7
|
+
_ => [x, ...({"f": f, "c": rest} | @)],
|
|
8
|
+
),
|
|
9
|
+
{"f": f ? @Function, "c": obj ? @Object} =>
|
|
10
|
+
{"f": (e => e | ([_, v] => v | f)), "c": {"f": (k => [k, obj[k]]), "c": obj | @keys} | @map} | @ | @toObject,
|
|
11
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@filter", "status": 0, "input": x, "expected": ["{\"f\": _ ? @Function, \"c\": _ ? @Array}", "{\"f\": _ ? @Function, \"c\": _ ? @Object}"]}
|
|
12
|
+
)
|
data/stdlib/flatten.fsn
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Recursively flatten nested arrays into one flat array.
|
|
2
|
+
(
|
|
3
|
+
[] => [],
|
|
4
|
+
[x ? @Array, ...rest] => [...(x | @), ...(rest | @)],
|
|
5
|
+
[x, ...rest] => [x, ...(rest | @)],
|
|
6
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@flatten", "status": 0, "input": x, "expected": ["_ ? @Array"]}
|
|
7
|
+
)
|
data/stdlib/gt.fsn
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Strictly greater: interprets an @OP.compare result. Use as `[a, b] | @OP.compare | @gt`.
|
|
2
|
+
# A partial order's compare may return null (incomparable); that propagates as null.
|
|
3
|
+
(
|
|
4
|
+
-1 => false,
|
|
5
|
+
0 => false,
|
|
6
|
+
1 => true,
|
|
7
|
+
null => null,
|
|
8
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@gt", "status": 0, "input": x, "expected": ["-1", "0", "1", "null"]},
|
|
9
|
+
)
|
data/stdlib/gte.fsn
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Greater-or-equal: interprets an @OP.compare result. Use as `[a, b] | @OP.compare | @gte`.
|
|
2
|
+
# A partial order's compare may return null (incomparable); that propagates as null.
|
|
3
|
+
(
|
|
4
|
+
-1 => false,
|
|
5
|
+
0 => true,
|
|
6
|
+
1 => true,
|
|
7
|
+
null => null,
|
|
8
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@gte", "status": 0, "input": x, "expected": ["-1", "0", "1", "null"]},
|
|
9
|
+
)
|
data/stdlib/lt.fsn
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Strictly less: interprets an @OP.compare result. Use as `[a, b] | @OP.compare | @lt`.
|
|
2
|
+
# A partial order's compare may return null (incomparable); that propagates as null.
|
|
3
|
+
(
|
|
4
|
+
-1 => true,
|
|
5
|
+
0 => false,
|
|
6
|
+
1 => false,
|
|
7
|
+
null => null,
|
|
8
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@lt", "status": 0, "input": x, "expected": ["-1", "0", "1", "null"]},
|
|
9
|
+
)
|
data/stdlib/lte.fsn
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Less-or-equal: interprets an @OP.compare result. Use as `[a, b] | @OP.compare | @lte`.
|
|
2
|
+
# A partial order's compare may return null (incomparable); that propagates as null.
|
|
3
|
+
(
|
|
4
|
+
-1 => true,
|
|
5
|
+
0 => true,
|
|
6
|
+
1 => false,
|
|
7
|
+
null => null,
|
|
8
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@lte", "status": 0, "input": x, "expected": ["-1", "0", "1", "null"]},
|
|
9
|
+
)
|
data/stdlib/map.fsn
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
# Apply f to each element of an array, or to each value of an object (keeping the
|
|
2
|
+
# keys). Input: {"f": fn, "c": array-or-object}.
|
|
1
3
|
(
|
|
2
|
-
{"f": _, "
|
|
3
|
-
{"f": f, "
|
|
4
|
+
{"f": _ ? @Function, "c": []} => [],
|
|
5
|
+
{"f": f ? @Function, "c": [x, ...rest]} => [x | f, ...({"f": f, "c": rest} | @)],
|
|
6
|
+
{"f": f ? @Function, "c": obj ? @Object} => {"f": (k => [k, obj[k] | f]), "c": obj | @keys} | @ | @toObject,
|
|
7
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@map", "status": 0, "input": x, "expected": ["{\"f\": _ ? @Function, \"c\": _ ? @Array}", "{\"f\": _ ? @Function, \"c\": _ ? @Object}"]}
|
|
4
8
|
)
|
data/stdlib/range.fsn
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
(
|
|
2
2
|
0 => [],
|
|
3
|
-
n ? @Integer => [...([n, 1] | @
|
|
3
|
+
n ? (m ? @Integer => [m, 0] | @OP.compare | @gt) => [...([n, -1] | @OP.sum | @), [n, -1] | @OP.sum],
|
|
4
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@range", "status": 0, "input": x, "expected": ["_ ? (m ? @Integer => [m, 0] | @OP.compare | @gte)"]}
|
|
4
5
|
)
|
data/stdlib/reduce.fsn
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Left fold over a NON-EMPTY array with no seed: combine the first two elements
|
|
2
|
+
# with f, then fold that result with the rest. Input: {"f": binaryFn, "c": array}.
|
|
3
|
+
# `f` receives the pair [acc, element]. An empty list is an error.
|
|
4
|
+
(
|
|
5
|
+
{"f": _ ? @Function, "c": [x]} => x,
|
|
6
|
+
{"f": f ? @Function, "c": [x, y, ...rest]} => {"f": f, "c": [[x, y] | f, ...rest]} | @,
|
|
7
|
+
x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@reduce", "status": 0, "input": x, "expected": ["{\"f\": _ ? @Function, \"c\": [_, ...]}"]}
|
|
8
|
+
)
|
data/stdlib/sanitize.fsn
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Render a value safe to embed in an error payload, mirroring the interpreter's
|
|
2
|
+
# lenient serialization (docs/user/reference.md §9.3): a function becomes
|
|
3
|
+
# "<function>" and a non-finite number becomes "<Infinity>" / "<-Infinity>" /
|
|
4
|
+
# "<NaN>". Arrays and objects are sanitized recursively; everything else is
|
|
5
|
+
# returned unchanged.
|
|
6
|
+
(
|
|
7
|
+
v ? @Function => "<function>",
|
|
8
|
+
v ? @NonFinite => [["<", v | @toString] | @concat, ">"] | @concat,
|
|
9
|
+
v ? @Array => {"f": @sanitize, "c": v} | @map,
|
|
10
|
+
v ? @Object => {"f": @sanitize, "c": v} | @map,
|
|
11
|
+
v => v
|
|
12
|
+
)
|
data/stdlib/truthy.fsn
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fusion-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.1
|
|
4
|
+
version: 0.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Klaus Weidinger
|
|
@@ -22,22 +22,61 @@ files:
|
|
|
22
22
|
- Rakefile
|
|
23
23
|
- docs/index.md
|
|
24
24
|
- docs/lang/design.md
|
|
25
|
+
- docs/lang/implementation.md
|
|
25
26
|
- docs/lang/roadmap.md
|
|
26
27
|
- docs/user/explanation.md
|
|
27
28
|
- docs/user/how-to-guides.md
|
|
28
29
|
- docs/user/reference.md
|
|
29
30
|
- docs/user/tutorial.md
|
|
30
31
|
- examples/double.fsn
|
|
32
|
+
- examples/ends.fsn
|
|
31
33
|
- examples/factorial.fsn
|
|
32
34
|
- examples/first.fsn
|
|
33
35
|
- examples/fizzbuzz.fsn
|
|
36
|
+
- examples/json_test.fsn
|
|
34
37
|
- examples/palindrome.fsn
|
|
35
38
|
- exe/fusion
|
|
36
39
|
- lib/fusion.rb
|
|
40
|
+
- lib/fusion/ast.rb
|
|
41
|
+
- lib/fusion/atom.rb
|
|
42
|
+
- lib/fusion/cli.rb
|
|
43
|
+
- lib/fusion/cli/decoder.rb
|
|
44
|
+
- lib/fusion/cli/encoder.rb
|
|
45
|
+
- lib/fusion/cli/options.rb
|
|
46
|
+
- lib/fusion/cli/parser.rb
|
|
47
|
+
- lib/fusion/cli/repl.rb
|
|
48
|
+
- lib/fusion/cli/serializer.rb
|
|
49
|
+
- lib/fusion/interpreter.rb
|
|
50
|
+
- lib/fusion/interpreter/builtins.rb
|
|
51
|
+
- lib/fusion/interpreter/env.rb
|
|
52
|
+
- lib/fusion/interpreter/error_val.rb
|
|
53
|
+
- lib/fusion/interpreter/func.rb
|
|
54
|
+
- lib/fusion/interpreter/native_func.rb
|
|
55
|
+
- lib/fusion/interpreter/thunk.rb
|
|
56
|
+
- lib/fusion/lexer.rb
|
|
57
|
+
- lib/fusion/null.rb
|
|
58
|
+
- lib/fusion/parser.rb
|
|
59
|
+
- lib/fusion/token.rb
|
|
60
|
+
- lib/fusion/typed_data.rb
|
|
37
61
|
- lib/fusion/version.rb
|
|
62
|
+
- lib/fusion/wire_pair.rb
|
|
63
|
+
- stdlib/all.fsn
|
|
64
|
+
- stdlib/any.fsn
|
|
65
|
+
- stdlib/chars.fsn
|
|
66
|
+
- stdlib/compact.fsn
|
|
67
|
+
- stdlib/concat.fsn
|
|
68
|
+
- stdlib/falsey.fsn
|
|
69
|
+
- stdlib/filter.fsn
|
|
70
|
+
- stdlib/flatten.fsn
|
|
71
|
+
- stdlib/gt.fsn
|
|
72
|
+
- stdlib/gte.fsn
|
|
73
|
+
- stdlib/lt.fsn
|
|
74
|
+
- stdlib/lte.fsn
|
|
38
75
|
- stdlib/map.fsn
|
|
39
|
-
- stdlib/math/square.fsn
|
|
40
76
|
- stdlib/range.fsn
|
|
77
|
+
- stdlib/reduce.fsn
|
|
78
|
+
- stdlib/sanitize.fsn
|
|
79
|
+
- stdlib/truthy.fsn
|
|
41
80
|
homepage: https://github.com/dunkelziffer/fusion
|
|
42
81
|
licenses:
|
|
43
82
|
- MIT
|
data/stdlib/math/square.fsn
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(n ? @Integer => [n, n] | @multiply)
|