You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: tutorial_content.md
+267Lines changed: 267 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -96,3 +96,270 @@ class RickrollInterpreter:
96
96
```
97
97
You can look into the Rickroll source code, [src-py/Interpreter.py](https://github.com/Rick-Lang/rickroll-lang/blob/main/src/interpreter.py) for a more complete implementation.
98
98
99
+
## Interpreter (continued)
100
+
101
+
Earlier we introduced the idea that an interpreter executes code *directly* from an AST. Let’s now complete the mental model.
102
+
103
+
### Environment / State
104
+
105
+
A real interpreter must track **state**:
106
+
107
+
* variables
108
+
* function definitions
109
+
* scopes
110
+
111
+
This is usually done with a dictionary (or stack of dictionaries).
112
+
113
+
Example:
114
+
115
+
```python
116
+
self.env = {}
117
+
```
118
+
119
+
When the interpreter encounters:
120
+
121
+
```rickroll
122
+
never gonna give x up 5
123
+
```
124
+
125
+
It updates the environment:
126
+
127
+
```python
128
+
self.env["x"] =5
129
+
```
130
+
131
+
Later, when `x` is referenced, the interpreter looks it up from `self.env`.
132
+
133
+
This is how *memory* exists in an interpreted language.
134
+
135
+
---
136
+
137
+
### Expression Evaluation
138
+
139
+
Statements like:
140
+
141
+
```rickroll
142
+
together forever x + 1
143
+
```
144
+
145
+
are expressions. Expressions must be **evaluated** before they can be used.
146
+
147
+
Typical evaluation steps:
148
+
149
+
1. Evaluate left operand
150
+
2. Evaluate right operand
151
+
3. Apply operator
152
+
153
+
Example AST:
154
+
155
+
```python
156
+
['+', 'x', '1']
157
+
```
158
+
159
+
Evaluation:
160
+
161
+
```python
162
+
defeval_expr(self, node):
163
+
ifisinstance(node, str):
164
+
if node.isdigit():
165
+
returnint(node)
166
+
returnself.env[node]
167
+
left =self.eval_expr(node[1])
168
+
right =self.eval_expr(node[2])
169
+
return left + right
170
+
```
171
+
172
+
This pattern repeats for:
173
+
174
+
* arithmetic
175
+
* comparisons
176
+
* logical operators
177
+
178
+
Congratulations — you just built a calculator that understands Rick Astley lyrics.
179
+
180
+
---
181
+
182
+
### Control Flow (If / Loop)
183
+
184
+
Control flow is what separates a toy language from a real one.
185
+
186
+
#### If statements
187
+
188
+
Already covered structurally, but execution matters:
189
+
190
+
```python
191
+
if condition:
192
+
execute_block()
193
+
else:
194
+
skip_block()
195
+
```
196
+
197
+
In AST form:
198
+
199
+
```python
200
+
['if', condition_node, body_node]
201
+
```
202
+
203
+
The interpreter:
204
+
205
+
1. Evaluates the condition
206
+
2. Executes the body **only if true**
207
+
208
+
---
209
+
210
+
#### Loops
211
+
212
+
Loops are just repeated condition checks.
213
+
214
+
Example AST:
215
+
216
+
```python
217
+
['while', condition, body]
218
+
```
219
+
220
+
Interpreter logic:
221
+
222
+
```python
223
+
whileself.evaluate_node(condition):
224
+
self.evaluate_node(body)
225
+
```
226
+
227
+
This is *exactly* how Turing completeness sneaks in.
228
+
229
+
---
230
+
231
+
### Why Interpreters Are Powerful
232
+
233
+
Interpreters:
234
+
235
+
* Are easier to implement than compilers
236
+
* Are great for rapid development
237
+
* Enable REPLs and interactive environments
238
+
* Can inspect and modify execution at runtime
239
+
240
+
This is why Python, Lua, and JavaScript thrive.
241
+
242
+
Downside?
243
+
Speed. Interpreters trade raw performance for flexibility.
244
+
245
+
---
246
+
247
+
# Making a Compiler (Conceptual Overview)
248
+
249
+
Rickroll-lang already supports transpiling and interpreting, but understanding compilation completes the picture.
250
+
251
+
A **compiler** pipeline looks like this:
252
+
253
+
```
254
+
Source Code
255
+
↓
256
+
Lexer
257
+
↓
258
+
Parser
259
+
↓
260
+
AST
261
+
↓
262
+
Optimizer (optional)
263
+
↓
264
+
Code Generator
265
+
↓
266
+
Machine Code / Bytecode
267
+
```
268
+
269
+
Key difference:
270
+
271
+
> **Compiled code runs without the source present**
272
+
273
+
---
274
+
275
+
## Intermediate Representation (IR)
276
+
277
+
Instead of compiling directly to machine code, many compilers use an **IR**.
278
+
279
+
Why?
280
+
281
+
* Platform independence
282
+
* Easier optimization
283
+
* Cleaner backend design
284
+
285
+
Rickroll could theoretically compile to:
286
+
287
+
* LLVM IR
288
+
* C code
289
+
* Bytecode
290
+
291
+
Transpiling to Python is already a form of IR usage — Python is the *runtime target*.
292
+
293
+
---
294
+
295
+
## Optimization (Optional, but Fun)
296
+
297
+
Examples:
298
+
299
+
* Constant folding
300
+
`2 + 3 → 5`
301
+
* Dead code elimination
302
+
Code after `return`
303
+
* Loop invariant lifting
304
+
305
+
Rickroll doesn’t *need* this — but knowing where it fits matters.
306
+
307
+
---
308
+
309
+
# JIT Compilation (Why It Exists)
310
+
311
+
A **JIT compiler** is an interpreter with ambition.
312
+
313
+
Workflow:
314
+
315
+
1. Interpret code normally
316
+
2. Detect hot paths (frequently executed)
317
+
3. Compile those paths to native code
318
+
4. Replace interpreter execution
319
+
320
+
Languages that do this:
321
+
322
+
* Java (HotSpot)
323
+
* JavaScript (V8)
324
+
* PyPy
325
+
326
+
Rickroll doesn’t do JIT — but now you understand why JIT exists.
327
+
328
+
---
329
+
330
+
# Big Picture: One Language, Many Implementations
331
+
332
+
Rickroll Programming Language supports:
333
+
334
+
* ✅ Transpiling (Rickroll → Python)
335
+
* ✅ Interpreting (AST + VM)
336
+
* ❌ Native compilation (yet)
337
+
338
+
And that’s the point of this project.
339
+
340
+
Same language.
341
+
Different execution strategies.
342
+
Same semantics.
343
+
344
+
---
345
+
346
+
# Why Rickroll Is a Great Teaching Language
347
+
348
+
Rickroll-lang succeeds because:
349
+
350
+
* Syntax is memorable (you *will* remember `never gonna give`)
0 commit comments