fez-lisp 1.5.202 → 1.6.0

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.
package/README.md CHANGED
@@ -25,3 +25,236 @@
25
25
  ```
26
26
 
27
27
  ## ⚠️ Important: Do not use this programming language in production!
28
+
29
+ ```lisp
30
+ ; Lisp programming language. It's not exactly like other Lisps.
31
+ ; Everything is an expression.
32
+
33
+ ; Important Note:
34
+ ; In this programming language, parentheses are used to group expressions and define the structure of code.
35
+ ; It is essential to keep the number of opening and closing parentheses balanced.
36
+ ; Unbalanced parentheses can lead to syntax errors or unexpected behavior in the code.
37
+ ; Always double-check your parentheses to ensure they match correctly.
38
+
39
+ ; Note: In this language, you can't have a value float outside by itself.
40
+ ; The final value must be wrapped in (identity ...), in an array [result],
41
+ ; or be the result of a function or a do block.
42
+
43
+ ; Note: Built in variable name like 'loop' 'if' 'do' are forbidden in this language.
44
+ ; If the block in an 'if' statement contains more than one expression, you must use 'do' to wrap those expressions.
45
+
46
+ ; You can wrap multiple results in an array, e.g. [(f 1) (f 2)], to return and compare multiple outputs at once.
47
+ ; This is handy compared to using identity, which only returns one value.
48
+
49
+ ; The condition in an if statement must be strictly 1 or 0, not just any non-nil value.
50
+ ; Use (truthy? ...) or (falsy? ...) to convert values to 1 or 0 for if conditions.
51
+ ; If a branch of if has multiple expressions, wrap them in a do block.
52
+
53
+ ; By default, if an if statement has only one branch, the else branch will be nil.
54
+
55
+ ; If you write (if condition then), the language will automatically add nil as the else branch, so it is equivalent to (if condition then nil).
56
+ ; nil is equivalent to 0 in this language.
57
+
58
+ ; For lambda, if a function takes no arguments, do not provide an argument list; just write (lambda body).
59
+ ; The last argument to lambda is always the body.
60
+
61
+ ; IMPORTANT: Do not use the 'tail-call:' prefix unless you are absolutely certain the function can be tail-call optimized (TCO).
62
+ ; For branching recursion (such as DFS, flood fill, tree/graph traversal, etc.), do NOT use 'tail-call:'.
63
+ ; Only use 'tail-call:' for linear/tail-position recursion (like loops or accumulators).
64
+ ; Similarly, only use 'memoized:' if you specifically want memoization for the function.
65
+ ; Be conservative with both prefixes, even if you see them in examples.
66
+
67
+ ; Lambda functions:
68
+ ; If a lambda body has more than one expression, you must wrap the body in a (do ...) block.
69
+ ; Example:
70
+ (lambda x y (do (let z (+ x y)) (* z 2)))
71
+ ; If the lambda body is a single expression, you do not need (do ...).
72
+
73
+ (let x 10) ; define a variable x with the value 10
74
+ (let xs (array 1 2 3 4)) ; define an array xs with initial values
75
+
76
+ (let add (lambda a b (do
77
+ (+ a b))) ; define a function add that takes two parameters a and b
78
+ )
79
+
80
+ ; Array operations
81
+ (array:set! xs 0 100) ; set the first element of array xs to 100
82
+ (set! xs 0 100) ; same as above
83
+ (array:pop! xs) ; remove the last element of array xs
84
+ (pop! xs) ; same as above
85
+ (array:push! xs (length xs) 10) ; add the value 10 at the end of array xs
86
+ (array:get xs 0) ; get the first element of array xs
87
+ (get xs 0) ; same as above
88
+
89
+ ; Note: set! and pop! are functions that update arrays (set! xs idx value, pop! xs). If you want to update variables (scalars), use the variable helpers: var:def to define, var:set! to update, and var:get to retrieve the value.
90
+
91
+ ; Mathematical operations
92
+ (+ (+ 1 2) x) ; add 1, 2, and x
93
+ (add (add 1 2) x) ; same as above but using the add function
94
+ (- 1) ; negate 1 to get -1
95
+ (- x 1) ; subtract 1 from x
96
+ (* x 10) ; multiply x by 10
97
+ (/ x 2) ; divide x by 2
98
+
99
+ ; Bitwise operations
100
+ (>> 1 2) ; right shift 1 by 2 bits
101
+ (<< 4 2) ; left shift 4 by 2 bits
102
+ (| 2 4) ; bitwise OR between 2 and 4
103
+ (~ 2) ; bitwise NOT of 2
104
+ (^ 5 7) ; bitwise XOR between 5 and 7
105
+ (& 4 3) ; bitwise AND between 4 and 3
106
+
107
+ ; Numeric functions
108
+ (math:abs -1) ; absolute value of -1
109
+ (math:floor 1.2) ; largest integer less than or equal to 1.2
110
+ (math:ceil 1.2) ; smallest integer greater than or equal to 1.2
111
+ (math:round 1.5) ; round 1.5 to the nearest integer
112
+ (math:max 2 3) ; maximum of 2 and 3
113
+ (math:min 4 3) ; minimum of 4 and 3
114
+ (math:power 4 2) ; raise 4 to the power of 4
115
+ (math:sqrt 9) ; fomd the square root of 9
116
+
117
+ ; Boolean operations
118
+ (and false true) ; logical AND
119
+ (or false true) ; logical OR
120
+ (not false) ; logical NOT
121
+
122
+ ; Comparisons
123
+ (> 1 2) ; check if 1 is greater than 2
124
+ (< 2 3) ; check if 2 is less than 3
125
+ (>= 1 2) ; check if 1 is greater than or equal to 2
126
+ (<= 2 2) ; check if 2 is less than or equal to 2
127
+ (= 1 1) ; check if 1 is equal to 1
128
+
129
+ ; If expression
130
+ (if (= 1 2) 10 -1) ; if 1 equals 2, return 10; otherwise, return -1
131
+ (let y (if (> 2 1) (add 1 2) (add 2 3))) ; assign to y based on condition
132
+
133
+ ; Cond expression (multiple conditions)
134
+ ; Use cond for multiple if-else conditions. Each clause has a condition and result.
135
+ ; The (*) clause is the default/else case and is REQUIRED as the last clause.
136
+ (cond
137
+ (= x 1) "one"
138
+ (= x 2) "two"
139
+ (= x 3) "three"
140
+ (*) "unknown") ; default case - REQUIRED
141
+
142
+ ; Cond with do blocks for multiple expressions
143
+ (cond
144
+ (= bill 5) (do (math:var-increment! fives) true)
145
+ (= bill 10) (if (> (math:var-get fives) 0)
146
+ (do (math:var-decrement! fives) (math:var-increment! tens) true)
147
+ false)
148
+ (*) false) ; default case - REQUIRED
149
+
150
+ ; Using do for multiple expressions
151
+ (if (> 2 1) (do
152
+ (let x 10) ; define x
153
+ (let y 23) ; define y
154
+ (+ x y)) ; return the sum of x and y
155
+ -10) ; if condition is false, return -10
156
+
157
+ ; Strings are represented as arrays of character codes
158
+ ; Example: "Hello World!" is represented as:
159
+ (array 72 101 108 108 111 32 87 111 114 108 100 33)
160
+
161
+ ; Variable operations
162
+ (let variable (var:def 0)) ; define a variable named variable with initial value 0
163
+ (var:set! variable (+ (var:get variable) 1)) ; increment variable by 1
164
+ (var:get variable) ; retrieve the value of variable (should be 1)
165
+
166
+ ; IMPORTANT: Variable Handling and set! Usage
167
+ ; ===========================================
168
+ ;
169
+ ; set! is ONLY for arrays - it cannot be used to update scalar variables.
170
+ ; If you want to update variables (scalars), use the appropriate variable helper functions.
171
+ ;
172
+ ; There are three types of variable systems in this language:
173
+ ;
174
+ ; 1. var:* - General purpose variables (any type)
175
+ (var:def value) ; - Define a variable with initial value
176
+ (var:set! var value) ; - Set variable to new value
177
+ (var:get var) ; - Get current value of variable
178
+ (var:del! var) ; - Delete/destroy variable
179
+
180
+ ; 2. math:var-* - Numeric variables (numbers only)
181
+ (math:var-def number) ; - Define a numeric variable
182
+ (math:var-set! var number) ; - Set numeric variable to new number
183
+ (math:var-get var) ; - Get current numeric value
184
+ (math:var-increment! var) ; - Add 1 to numeric variable
185
+ (math:var-decrement! var) ; - Subtract 1 from numeric variable
186
+ (math:var-add! var x) ; - Add x to numeric variable
187
+ (math:var-subtract! var x) ; - Subtract x from numeric variable
188
+ ;
189
+ ; 3. bool:* - Boolean variables (true/false only)
190
+ (bool:true) ; - Create boolean variable initialized to true
191
+ (bool:false) ; - Create boolean variable initialized to false
192
+ (bool:true! var) ; - Set boolean variable to true
193
+ (bool:false! var) ; - Set boolean variable to false
194
+ (bool:true? var) ; - Check if boolean variable is true
195
+ (bool:false? var) ; - Check if boolean variable is false
196
+ ;
197
+ ; Examples:
198
+ (let counter (math:var-def 0)) ; numeric variable
199
+ (math:var-increment! counter) ; increment by 1
200
+ (math:var-set! counter 10) ; set to 10
201
+
202
+ (let found (bool:false)) ; boolean variable
203
+ (bool:true! found) ; set to true
204
+ (if (bool:true? found) "yes" "no") ; check if true
205
+
206
+ (let data (var:def "hello")) ; general variable
207
+ (var:set! data "world") ; set to new value
208
+ (var:get data) ; get current value
209
+ ;
210
+ ; WRONG: (set! counter 5) ; ERROR: set! only works on arrays
211
+ ; RIGHT: (math:var-set! counter 5) ; Use appropriate variable function
212
+ ;
213
+ ; Array operations (set! works here):
214
+ (let arr [1 2 3])
215
+ (set! arr 0 100) ; Set array element at index 0 to 100
216
+ (array:set! arr 1 200) ; Same as above
217
+
218
+ ; Defining functions to reverse an array
219
+ (let arr:for (lambda xs cb (do
220
+ (let tail-call:arr:for (lambda i (do
221
+ (if (> (length xs) i) (do
222
+ (cb (get xs i)) ; apply callback to current element
223
+ ; recurse to next index
224
+ (tail-call:arr:for (+ i 1)))
225
+ ; return 0 when done
226
+ 0))))
227
+ (tail-call:arr:for 0)
228
+ xs)))
229
+ (let arr:merge (lambda a b (do
230
+ (let out (array)) initialize an empty array for output
231
+ (arr:for a (lambda x (do (set! out (length out) x))))
232
+ (arr:for b (lambda x (do (set! out (length out) x)))) out)))
233
+ (let arr:reverse (lambda xs (do
234
+ (let tail-call:arr:reverse (lambda i out (do
235
+ (if (> (length xs) i)
236
+ (tail-call:arr:reverse (+ i 1)
237
+ (arr:merge (array (get xs i)) out))
238
+ out))))
239
+ (tail-call:arr:reverse 0 (array)))))
240
+ (arr:reverse (array 1 2 3)) ; 3 2 1
241
+ ; Make sure ypu keep the parens balanced
242
+
243
+ ; these are syntactic suggar for the language but you don't need to use them
244
+ ; syntactic suggar for array
245
+ [ 1 2 3 4 5 ]
246
+ ; syntactic suggar for linked list
247
+ { 1 2 3 4 5 }
248
+ ; array destructuring
249
+ [ a b . c ]
250
+ ; list destructuring
251
+ { a b . c }
252
+ ; . means skip that element and last one is aways the rest unelss skipped
253
+ [ a . b c ]
254
+ [ a b . ]
255
+ ; pipe operator
256
+ (|> 1 (+ 1 2) (* 3 4))
257
+ ; pipe operator with destructuring
258
+
259
+ "Hello World!" ; syntactic suggar for string but it's array of character codes
260
+ ```
@@ -148,7 +148,7 @@ export const SLICE_RAW = [
148
148
  ],
149
149
  [
150
150
  [0, 'let'],
151
- [1, 'recursive:iterate'],
151
+ [1, 'tail-call:iterate'],
152
152
  [
153
153
  [0, 'lambda'],
154
154
  [1, 'i'],
@@ -161,7 +161,7 @@ export const SLICE_RAW = [
161
161
  [1, 'bounds']
162
162
  ],
163
163
  [
164
- [0, 'recursive:iterate'],
164
+ [0, 'tail-call:iterate'],
165
165
  [
166
166
  [0, '+'],
167
167
  [1, 'i'],
@@ -189,6 +189,6 @@ export const SLICE_RAW = [
189
189
  ]
190
190
  ]
191
191
  ],
192
- [[0, 'recursive:iterate'], [2, 0], []]
192
+ [[0, 'tail-call:iterate'], [2, 0], []]
193
193
  ]
194
194
  ]