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
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # === Interpreter internals ===
4
+ #
5
+ # Lazy, memoized value of a top-level unit (a file, or an inline/REPL entry).
6
+
7
+ module Fusion
8
+ class Interpreter
9
+ class Thunk
10
+ # We use a custom Ruby error to transmit read failures between `Interpreter.evaluate_file`
11
+ # (which runs in the @compute block) and the Thunk to enforce their connection.
12
+ # If `Interpreter.evaluate_file` were to be used outside of a Thunk, the Ruby error would
13
+ # bubble and trigger an `internal_error` later on.
14
+ class ReadFailure < StandardError; end
15
+
16
+ def initialize(&compute)
17
+ @compute = compute
18
+ @state = :unforced # :unforced | :forcing | :done
19
+ @value = nil # memoized result: runtime value/error | ReadFailure
20
+ end
21
+
22
+ # `operation`/`input`/`site` describe the @-reference forcing this thunk.
23
+ # They are NOT passed to `@compute`, because they differ when evaluating the same
24
+ # Thunk for different @-references. They MUST NOT become part or the memoized value.
25
+ def force(operation: "loading code", input: NULL, site: { origin: "code", file: nil })
26
+ result = case @state
27
+ when :done
28
+ @value
29
+ when :forcing
30
+ # Re-entering while still computing results in a non-productive data cycle. Not memoized.
31
+ ErrorVal.from_runtime(kind: "reference_error", **site, operation: operation, input: input, message: "non-productive data cycle")
32
+ when :unforced
33
+ @state = :forcing
34
+ begin
35
+ @value = @compute.call
36
+ rescue ReadFailure => failure
37
+ # Memoize the Ruby error itself. Turn it into a Fusion runtime error below.
38
+ @value = failure
39
+ end
40
+ @state = :done
41
+ @value
42
+ end
43
+
44
+ case result
45
+ when ReadFailure
46
+ ErrorVal.from_runtime(kind: "reference_error", **site, operation: operation, input: input, message: result.message)
47
+ else
48
+ result
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end