beginnings of REPL
[muddle-interpreter.git] / doc / MISC_NOTES.md
1 # Design goals
2
3 ## Compatibility
4
5 Support the same language as the original interpreter, except for
6 platform differences.
7
8 ## Architectural faithfulness
9
10 Try to maintain the spirit of the initial implementation.
11
12 The original was written in assembly and ran in environments we'd now
13 consider extremely memory constrained. Update the design to fit new
14 platforms, but don't expand its resource requirements to fit the glut
15 of available memory.
16
17 ## Suitability for new projects
18
19 The implementation should not be optimized for the PDP at the expense
20 of performance on modern hardware.
21
22 The language should not be complicated solely for backward
23 compatibility.
24
25 The runtime should not be larger or slower than necessitated by the
26 dynamism of the language.
27
28 # Distinctive features
29
30 ## Package system
31
32 The package-oriented nature of the language is a huge plus. Easy
33 sharing of packages along the lines of Quicklisp/MELPA/Cargo is a key
34 feature for building a community.
35
36 ## Coroutines (stackful)
37
38 ## Interrupt mechanism
39
40 Very powerful. In combination with coroutines, could be used to
41 implement pre-emptively multitasked green threads. Supports setting
42 "breakpoints" on variable accesses.
43
44 ## Fexprs
45
46 In Muddle there are no "magic" forms that can only be provided by the
47 runtime (or, anything can be magic). Disciplined use is required to
48 avoid madness, but sometimes FEXPRs can be clearer than macros.
49
50 ## First-class term-rewriting fexprs...
51
52 "CALL" is the most (dangerously) powerful language feature I've ever
53 heard of.
54
55 ## Re-entrant first-class stack-allocated continuations
56
57 That can jump forward.
58
59 With UNWIND.
60
61 ## Powerful type system
62
63 ### Slot accessors
64
65 Simple accessors just evaluate to numbers that perform access into
66 vector slots, but the caller sees the same interface as if it were a
67 function.
68
69 ### Truthiness is an `Either` type
70
71 # language features
72
73 ## no tail call elimination
74
75 TCE would elide FRAMEs, and mess with ACTIVATIONs and stack introspection.
76
77 ## variable scope
78
79 * primarily dynamic, with namespaces
80 * lexical scoping features available
81   * e.g. PROG
82
83 ## coroutines (stackful)
84
85 ## evaluation model
86
87 ### fexprs: FSUBR, CALL/QUOTE/ARGS
88
89 Any "function" can accept arguments unevaluated, and then it may BIND
90 and EVAL them. Hence short-circuiting operators such as AND could be
91 defined as library functions.
92
93 ## locatives
94
95 * reference to a struct field
96
97 ## interrupts (PL-21)
98
99 * operationally similar to UNIX signals
100 * checked for a defined times (PL-21.7.1)
101 * could be implemented with an atomic flag
102
103 ## fixnums
104
105 * FIX is defined as a 36-bit integer
106 * by default, an error will be produced on overflow! this makes
107   compatibility easier than if software counted on wrapping...
108 * RANDOM returns a 36-bit random
109   * though code that compares <RANDOM> to <MAX> may be ok
110 * out of a 64-bit word, this leaves a lot of room for tags or something...
111
112 ## truth
113
114 * false/true is actually: left(list) / any
115 * T exists as true value carrying no additional information
116
117 ## uvector
118
119 * type-homogenous vector
120
121 ## closures
122
123 * since scope is dynamic, closure variables are captured explicitly
124
125 ## macros (PL-17)
126
127 # Packages
128
129 Package metadata:
130 * MANIFEST GVALs
131 * NEWTYPE definitions
132 * MACROs that don't depend on the package's functions
133 * RSUBR DECLs
134
135 # Mediation
136
137 The documentation refers to "mediation" when compiled code calls in to
138 the interpreter or interpreted code calls a compiled subroutine.
139
140 ## Mediated subroutine calls
141
142 Calls to `RSUBR`s that haven't been `SUBRIFY`'d are _mediated_ calls;
143 the interpreter does a full `MCALL`, and the compiled code has an
144 entry point that translates to a `BINCALL`.
145
146 # State machine
147
148 ## Non-local control flow
149
150 ### `ERRET` / return from
151 Check `PROCESS` id. Unwind stack until the specified `FRAME`. Return.
152
153 ### `RESUME`
154 Change `PROCESS` id. Return from new `PROCESS`es previous `RESUME`
155 frame with specified value.
156
157 ### `GO`/`TAG`
158 `TAG`: holds a pointer to an AST node, and the call depth of that
159 node's enclosing `PROG`.
160 `GO`: unwind to depth specified in `TAG`; resume execution.
161
162 ### `REPEAT`
163 Uwind to enclosing `PROG`; continue.