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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -6
  3. data/Rakefile +9 -0
  4. data/docs/lang/design.md +418 -28
  5. data/docs/lang/implementation.md +238 -0
  6. data/docs/lang/roadmap.md +20 -57
  7. data/docs/user/explanation.md +5 -10
  8. data/docs/user/how-to-guides.md +62 -23
  9. data/docs/user/reference.md +596 -168
  10. data/docs/user/tutorial.md +32 -29
  11. data/examples/double.fsn +1 -1
  12. data/examples/ends.fsn +4 -0
  13. data/examples/factorial.fsn +2 -2
  14. data/examples/fizzbuzz.fsn +1 -4
  15. data/examples/json_test.fsn +4 -0
  16. data/examples/palindrome.fsn +2 -1
  17. data/exe/fusion +17 -44
  18. data/lib/fusion/ast.rb +97 -0
  19. data/lib/fusion/atom.rb +17 -0
  20. data/lib/fusion/cli/decoder.rb +84 -0
  21. data/lib/fusion/cli/encoder.rb +28 -0
  22. data/lib/fusion/cli/options.rb +212 -0
  23. data/lib/fusion/cli/parser.rb +38 -0
  24. data/lib/fusion/cli/repl.rb +78 -0
  25. data/lib/fusion/cli/serializer.rb +70 -0
  26. data/lib/fusion/cli.rb +207 -0
  27. data/lib/fusion/interpreter/builtins.rb +465 -0
  28. data/lib/fusion/interpreter/env.rb +89 -0
  29. data/lib/fusion/interpreter/error_val.rb +71 -0
  30. data/lib/fusion/interpreter/func.rb +22 -0
  31. data/lib/fusion/interpreter/native_func.rb +22 -0
  32. data/lib/fusion/interpreter/thunk.rb +53 -0
  33. data/lib/fusion/interpreter.rb +752 -0
  34. data/lib/fusion/lexer.rb +249 -0
  35. data/lib/fusion/null.rb +9 -0
  36. data/lib/fusion/parser.rb +542 -0
  37. data/lib/fusion/token.rb +22 -0
  38. data/lib/fusion/typed_data.rb +23 -0
  39. data/lib/fusion/version.rb +1 -1
  40. data/lib/fusion/wire_pair.rb +11 -0
  41. data/lib/fusion.rb +11 -1122
  42. data/stdlib/all.fsn +13 -0
  43. data/stdlib/any.fsn +12 -0
  44. data/stdlib/chars.fsn +5 -0
  45. data/stdlib/compact.fsn +6 -0
  46. data/stdlib/concat.fsn +5 -0
  47. data/stdlib/falsey.fsn +6 -0
  48. data/stdlib/filter.fsn +12 -0
  49. data/stdlib/flatten.fsn +7 -0
  50. data/stdlib/gt.fsn +9 -0
  51. data/stdlib/gte.fsn +9 -0
  52. data/stdlib/lt.fsn +9 -0
  53. data/stdlib/lte.fsn +9 -0
  54. data/stdlib/map.fsn +6 -2
  55. data/stdlib/range.fsn +2 -1
  56. data/stdlib/reduce.fsn +8 -0
  57. data/stdlib/sanitize.fsn +12 -0
  58. data/stdlib/truthy.fsn +7 -0
  59. metadata +41 -2
  60. 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
@@ -0,0 +1,5 @@
1
+ # Split a string into its characters. Built on @split with an empty separator.
2
+ (
3
+ s ? @String => [s, ""] | @split,
4
+ x => !{"kind": "argument_error", "origin": "stdlib", "operation": "@chars", "status": 0, "input": x, "expected": ["_ ? @String"]}
5
+ )
@@ -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
@@ -0,0 +1,6 @@
1
+ # True for false and null — Fusion's own falsiness, decided by pattern matching.
2
+ (
3
+ false => true,
4
+ null => true,
5
+ _ => false,
6
+ )
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
+ )
@@ -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": _, "xs": []} => [],
3
- {"f": f, "xs": [x, ...rest]} => [x | f, ...({"f": f, "xs": rest} | @map)]
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] | @subtract | @range), [n, 1] | @subtract]
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
+ )
@@ -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
@@ -0,0 +1,7 @@
1
+ # True for every value except false and null — Fusion's own truthiness, decided by
2
+ # pattern matching, so it is independent of any @OP override.
3
+ (
4
+ false => false,
5
+ null => false,
6
+ _ => true,
7
+ )
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.alpha1
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
@@ -1 +0,0 @@
1
- (n ? @Integer => [n, n] | @multiply)