1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
RegEx stuff: http://sebfisch.github.com/haskell-regexp/
= Expressions =
0 1 2... -> just push themselves on the stack
"string" -> pushes "string" on the stack
<non-bareword><bareword> -> "bareword" <non-bareword>
/bareword -> "bareword" /
|bareword -> "bareword" |
\bareword -> "bareword" \
bareword -> lookup "bareword" in current scopes
-> passive -> push value on the stack
-> active -> call value on current stack
-> quote -> call value on current stack, even in quoted mode
/ -> nop
"string" | -> resolve "string" in current scope, push value
"string" \ -> resolve "string" in current scope, call value on current stack
[ -> push array begin marker on stack
] -> since the topmost array marker, create array from stack values
( -> push tuple begin marker on stack
) -> since the topmost tuple marker, create tuple from stack values
{ -> push quote begin marker on stack, increase parser quote count
} -> since the topmost quote marker, everything becomes one closure (deduce type), decrease parser quote count
dup -> dups
|dup -> push dup function pointer
\dup -> dups
|f |g ; -> { f g }
{ ...1 } variable ; { ...2 } ; -> { ...1 variable } { ...2 } ; -> { ...1 variable ...2 }
1 2 |add * -> 3
|f * -> f
|f *10 g -> f <copy the former _10> g
StructuredData.field -> StructuredData "field" . -> dereference field in structured data, if passive push, if active do
SD "field" .| -> dereference, push value
SD "field" .\ -> dereference, call
x "string" = -> dereference, create (passive/active depends on type) field if not existent, set value to x
x pointer = -> dereference, set value to x
x /pointervar = -> sets the pointer itself
x |pointervar = -> sets the value the pointer points to
x \pointervar = -> if the pointer points to a value which is a pointer, assign where that pointer points to
v "name" deff -> define name as active name, assign v
v "name" defv -> define name as passive name, assign v
< -> push new scope
> -> pop scope, structured data object now on stack
< 0 =a 0 =b > -> something which has a and b is on top of stack
0 1 2 _0 -> 0 1 2 2
0 1 2 _1 -> 0 1 2 1
0 1 2 _2 -> 0 1 2 0
0 1 2 -0 -> 2
0 1 2 -1 -> 1
0 1 2 -2 -> 0
exch = -01
pop = -
nop = _
dup = _0
_<digits> -> copy stack contents according to digits
-<digits> -> delete stack contents up to largest digit or count of "-" whichever is larger, recreate according to digits
1 [ 2 3 ] add -> [ 3 4 ]
[ [ 1 ] [ 2 ] ] length -> 2 # scanning for applicable base type from top
A->int B->int add -> B->A->int
A->int A->int add -> A->int
= Characters =
!: <open>
": string quote
#: line comment
$: <open>
%: <open>
&: <open>
': <open>
(: tuple begin
): tuple end
*: apply function
+: <open>
,: <open>
-: stack manipulation
.: field dereference
/: stringify
0-9: numbers
:: <open>
;: function composition
<: scope start
=: assignment
>: scope end
?: ternary operator
@: <open>
A-Z: bareword characters
[: array begin
\: callify
]: array end
^: <open>
_: stack manipulation
`: <open>
a-z: bareword characters
{: quote begin
|: passify
}: quote end
~: <open>
= Memory Management =
Inspiration: http://wiki.luajit.org/new-garbage-collector
0x6???????????: Heap memory ("16 TB should be enough for everyone.")
0x5???????????: GC black bitmap
0x4???????????: GC allocation maps
Large set of reachable, old objects
Large set of unreachable, new objects
Small set in between
== Object Memory Layout ==
=== Int ===
* Length in bytes (including header, always 16)
bit 63-60: 0 0 0 0
bit 59: reserved for GC
* value
=== String ===
* Length in bytes (including header)
bit 63-60: 0 0 0 1
bit 59: reserved for GC
* hash (0 if not yet calculated)
* Exact length
* data (UTF-8)
=== Scope ===
* Length in bytes (including header)
bit 63-60: 0 0 1 0
bit 59: reserved for GC
bit 58: parent pointer exists (for scopes) (always 1 for now)
bit 57: extension area pointer exists (always 1 for now)
* name table (mapping entry names to offsets)
* parent scope (0 if no parent)
* extension area pointer (0 if no extra members (yet))
* data
[ <reference> ]*
=== Name Table ===
( TODO: create a hash-table based implementation here )
* Length in bytes (including header)
bit 63-60: 0 0 1 1
bit 59: reserved for GC
* End of fill in bytes (i.e. if this field == length, table is full)
* data
[ <string reference>, <execution mode> ]*
( TODO: Oh, the performance... )
The 0th string maps to 0 and so on.
=== Extension Area ===
* Length in bytes (including header)
bit 63-60: 0 1 0 0
bit 59: reserved for GC
* data
[ <reference> ]*
=== Function ===
* Length in bytes (including header)
bit 63-60: 0 1 0 1
bit 59: reserved for GC
* scope pointer (0 if non-capturing function)
* type pointer (0 if untyped)
* code pointer
=== Function Code ===
* Length in bytes (including header)
bit 63-60: 0 1 1 0
bit 59: reserved for GC
* [ <opcode> ]*
|