brittainscript 0.1.0__tar.gz → 0.3.0__tar.gz

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 (30) hide show
  1. {brittainscript-0.1.0 → brittainscript-0.3.0}/Documentation/README.md +112 -0
  2. {brittainscript-0.1.0 → brittainscript-0.3.0}/LICENSE +1 -1
  3. {brittainscript-0.1.0 → brittainscript-0.3.0}/PKG-INFO +114 -2
  4. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/PKG-INFO +114 -2
  5. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/SOURCES.txt +11 -1
  6. brittainscript-0.3.0/core/gui_backend.py +450 -0
  7. {brittainscript-0.1.0 → brittainscript-0.3.0}/core/lexer.py +11 -0
  8. {brittainscript-0.1.0 → brittainscript-0.3.0}/core/parser.py +191 -23
  9. brittainscript-0.3.0/core/parsetab.py +73 -0
  10. brittainscript-0.3.0/libs/datetime.bs +50 -0
  11. brittainscript-0.3.0/libs/gui.bs +156 -0
  12. brittainscript-0.3.0/libs/io.bs +28 -0
  13. brittainscript-0.3.0/libs/terminal.bs +49 -0
  14. {brittainscript-0.1.0 → brittainscript-0.3.0}/pyproject.toml +1 -1
  15. brittainscript-0.3.0/tests/test_datetime_builtin.py +54 -0
  16. brittainscript-0.3.0/tests/test_gui_builtins.py +43 -0
  17. brittainscript-0.3.0/tests/test_operator_precedence.py +59 -0
  18. brittainscript-0.3.0/tests/test_parser_builtins.py +39 -0
  19. brittainscript-0.3.0/tests/test_python_bridge.py +192 -0
  20. brittainscript-0.1.0/core/parsetab.py +0 -71
  21. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/dependency_links.txt +0 -0
  22. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/entry_points.txt +0 -0
  23. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/requires.txt +0 -0
  24. {brittainscript-0.1.0 → brittainscript-0.3.0}/brittainscript.egg-info/top_level.txt +0 -0
  25. {brittainscript-0.1.0 → brittainscript-0.3.0}/core/__init__.py +0 -0
  26. {brittainscript-0.1.0 → brittainscript-0.3.0}/core/main.py +0 -0
  27. {brittainscript-0.1.0 → brittainscript-0.3.0}/libs/__init__.py +0 -0
  28. {brittainscript-0.1.0 → brittainscript-0.3.0}/libs/convert.bs +0 -0
  29. {brittainscript-0.1.0 → brittainscript-0.3.0}/libs/math.bs +0 -0
  30. {brittainscript-0.1.0 → brittainscript-0.3.0}/setup.cfg +0 -0
@@ -180,6 +180,118 @@ push(len(nums))
180
180
 
181
181
  ---
182
182
 
183
+ ## Python Interop
184
+
185
+ BrittainScript can call into any Python library installed in the same Python
186
+ environment — `numpy`, `requests`, `torch`, anything. There is nothing to
187
+ install beyond the library itself; the interpreter's only dependency is `ply`.
188
+
189
+ ### `pyimport(name)`
190
+
191
+ Imports a Python module and hands it back as an ordinary BrittainScript value.
192
+
193
+ ```
194
+ np = pyimport("numpy")
195
+ json = pyimport("json")
196
+ ```
197
+
198
+ If the module cannot be imported, `pyimport` prints an error and returns
199
+ nothing:
200
+
201
+ ```
202
+ missing = pyimport("not_a_real_module")
203
+ => Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
204
+ ```
205
+
206
+ ### Calling Python methods
207
+
208
+ Method-call syntax falls through to Python whenever the name is not one of
209
+ BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
210
+ `add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
211
+ are unaffected.
212
+
213
+ ```
214
+ np = pyimport("numpy")
215
+ matrix = np.array([[1, 2], [3, 4]])
216
+
217
+ push(matrix.sum()) => 10
218
+ push(matrix.transpose())
219
+ push("a,b,c".split(",")) => ['a', 'b', 'c']
220
+ push("hello".replace("l", "L"))
221
+ ```
222
+
223
+ Note that arguments are positional only — BrittainScript has no keyword
224
+ argument syntax. Where a Python API needs a keyword, look for a method form of
225
+ it (`tensor.requires_grad_()` rather than `requires_grad=true`).
226
+
227
+ ### Attribute access
228
+
229
+ A dotted name with no call reads the attribute directly.
230
+
231
+ ```
232
+ np = pyimport("numpy")
233
+ matrix = np.array([[1, 2], [3, 4]])
234
+
235
+ push(matrix.shape) => (2, 2)
236
+ push(matrix.T)
237
+ push(pyimport("math").pi) => 3.141592653589793
238
+ ```
239
+
240
+ Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
241
+ names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
242
+
243
+ ### The `@` operator
244
+
245
+ `@` is matrix multiplication, passed straight through to Python's `__matmul__`.
246
+
247
+ ```
248
+ np = pyimport("numpy")
249
+ a = np.array([[1, 2], [3, 4]])
250
+ push(a @ a) => [[ 7 10]
251
+ [15 22]]
252
+ ```
253
+
254
+ It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
255
+
256
+ ### Why this works everywhere else too
257
+
258
+ BrittainScript values are native Python objects, so once a Python object is in
259
+ a variable, the rest of the language already applies to it — arithmetic,
260
+ indexing, slicing, comparison and `for` loops all use Python's own behaviour:
261
+
262
+ ```
263
+ np = pyimport("numpy")
264
+ values = np.array([10, 20, 30, 40])
265
+
266
+ push(values * 2)
267
+ push(values[1])
268
+ push(values[1:3])
269
+ for value in values:
270
+ push(value)
271
+ end
272
+ ```
273
+
274
+ ### A worked example
275
+
276
+ `examples/torch_demo.bs` trains a small linear model with PyTorch, including a
277
+ hand-written SGD loop driven by autograd. Run it with:
278
+
279
+ ```
280
+ python3 run.py examples/torch_demo.bs
281
+ ```
282
+
283
+ It prints a message and stops if `torch` is not installed.
284
+
285
+ ### A note on scope
286
+
287
+ `pyimport` gives a script the whole Python environment — including `os`,
288
+ `subprocess` and `shutil`. That is the expected trade-off for a scripting
289
+ language FFI and is the same power a Python script has, but it does mean a
290
+ `.bs` file can do anything the Python interpreter running it can do. Treat
291
+ untrusted BrittainScript the way you would treat untrusted Python.
292
+
293
+ ---
294
+
183
295
  ## Test Files
184
296
 
185
297
  There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 AstraStudios
3
+ Copyright (c) 2026 Luke Brittain
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brittainscript
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: The BrittainScript programming language interpreter
5
5
  Author-email: Luke Brittain <luke.brittain@gmail.com>
6
6
  License: MIT License
7
7
 
8
- Copyright (c) 2024 AstraStudios
8
+ Copyright (c) 2026 Luke Brittain
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  of this software and associated documentation files (the "Software"), to deal
@@ -218,6 +218,118 @@ push(len(nums))
218
218
 
219
219
  ---
220
220
 
221
+ ## Python Interop
222
+
223
+ BrittainScript can call into any Python library installed in the same Python
224
+ environment — `numpy`, `requests`, `torch`, anything. There is nothing to
225
+ install beyond the library itself; the interpreter's only dependency is `ply`.
226
+
227
+ ### `pyimport(name)`
228
+
229
+ Imports a Python module and hands it back as an ordinary BrittainScript value.
230
+
231
+ ```
232
+ np = pyimport("numpy")
233
+ json = pyimport("json")
234
+ ```
235
+
236
+ If the module cannot be imported, `pyimport` prints an error and returns
237
+ nothing:
238
+
239
+ ```
240
+ missing = pyimport("not_a_real_module")
241
+ => Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
242
+ ```
243
+
244
+ ### Calling Python methods
245
+
246
+ Method-call syntax falls through to Python whenever the name is not one of
247
+ BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
248
+ `add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
249
+ are unaffected.
250
+
251
+ ```
252
+ np = pyimport("numpy")
253
+ matrix = np.array([[1, 2], [3, 4]])
254
+
255
+ push(matrix.sum()) => 10
256
+ push(matrix.transpose())
257
+ push("a,b,c".split(",")) => ['a', 'b', 'c']
258
+ push("hello".replace("l", "L"))
259
+ ```
260
+
261
+ Note that arguments are positional only — BrittainScript has no keyword
262
+ argument syntax. Where a Python API needs a keyword, look for a method form of
263
+ it (`tensor.requires_grad_()` rather than `requires_grad=true`).
264
+
265
+ ### Attribute access
266
+
267
+ A dotted name with no call reads the attribute directly.
268
+
269
+ ```
270
+ np = pyimport("numpy")
271
+ matrix = np.array([[1, 2], [3, 4]])
272
+
273
+ push(matrix.shape) => (2, 2)
274
+ push(matrix.T)
275
+ push(pyimport("math").pi) => 3.141592653589793
276
+ ```
277
+
278
+ Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
279
+ names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
280
+
281
+ ### The `@` operator
282
+
283
+ `@` is matrix multiplication, passed straight through to Python's `__matmul__`.
284
+
285
+ ```
286
+ np = pyimport("numpy")
287
+ a = np.array([[1, 2], [3, 4]])
288
+ push(a @ a) => [[ 7 10]
289
+ [15 22]]
290
+ ```
291
+
292
+ It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
293
+
294
+ ### Why this works everywhere else too
295
+
296
+ BrittainScript values are native Python objects, so once a Python object is in
297
+ a variable, the rest of the language already applies to it — arithmetic,
298
+ indexing, slicing, comparison and `for` loops all use Python's own behaviour:
299
+
300
+ ```
301
+ np = pyimport("numpy")
302
+ values = np.array([10, 20, 30, 40])
303
+
304
+ push(values * 2)
305
+ push(values[1])
306
+ push(values[1:3])
307
+ for value in values:
308
+ push(value)
309
+ end
310
+ ```
311
+
312
+ ### A worked example
313
+
314
+ `examples/torch_demo.bs` trains a small linear model with PyTorch, including a
315
+ hand-written SGD loop driven by autograd. Run it with:
316
+
317
+ ```
318
+ python3 run.py examples/torch_demo.bs
319
+ ```
320
+
321
+ It prints a message and stops if `torch` is not installed.
322
+
323
+ ### A note on scope
324
+
325
+ `pyimport` gives a script the whole Python environment — including `os`,
326
+ `subprocess` and `shutil`. That is the expected trade-off for a scripting
327
+ language FFI and is the same power a Python script has, but it does mean a
328
+ `.bs` file can do anything the Python interpreter running it can do. Treat
329
+ untrusted BrittainScript the way you would treat untrusted Python.
330
+
331
+ ---
332
+
221
333
  ## Test Files
222
334
 
223
335
  There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brittainscript
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: The BrittainScript programming language interpreter
5
5
  Author-email: Luke Brittain <luke.brittain@gmail.com>
6
6
  License: MIT License
7
7
 
8
- Copyright (c) 2024 AstraStudios
8
+ Copyright (c) 2026 Luke Brittain
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  of this software and associated documentation files (the "Software"), to deal
@@ -218,6 +218,118 @@ push(len(nums))
218
218
 
219
219
  ---
220
220
 
221
+ ## Python Interop
222
+
223
+ BrittainScript can call into any Python library installed in the same Python
224
+ environment — `numpy`, `requests`, `torch`, anything. There is nothing to
225
+ install beyond the library itself; the interpreter's only dependency is `ply`.
226
+
227
+ ### `pyimport(name)`
228
+
229
+ Imports a Python module and hands it back as an ordinary BrittainScript value.
230
+
231
+ ```
232
+ np = pyimport("numpy")
233
+ json = pyimport("json")
234
+ ```
235
+
236
+ If the module cannot be imported, `pyimport` prints an error and returns
237
+ nothing:
238
+
239
+ ```
240
+ missing = pyimport("not_a_real_module")
241
+ => Error: cannot import 'not_a_real_module': No module named 'not_a_real_module'
242
+ ```
243
+
244
+ ### Calling Python methods
245
+
246
+ Method-call syntax falls through to Python whenever the name is not one of
247
+ BrittainScript's own methods (`upper`, `lower`, `trim`, `contains`, `locate`,
248
+ `add`, `remove`, `pop`, `has`). Those built-ins always win, so existing scripts
249
+ are unaffected.
250
+
251
+ ```
252
+ np = pyimport("numpy")
253
+ matrix = np.array([[1, 2], [3, 4]])
254
+
255
+ push(matrix.sum()) => 10
256
+ push(matrix.transpose())
257
+ push("a,b,c".split(",")) => ['a', 'b', 'c']
258
+ push("hello".replace("l", "L"))
259
+ ```
260
+
261
+ Note that arguments are positional only — BrittainScript has no keyword
262
+ argument syntax. Where a Python API needs a keyword, look for a method form of
263
+ it (`tensor.requires_grad_()` rather than `requires_grad=true`).
264
+
265
+ ### Attribute access
266
+
267
+ A dotted name with no call reads the attribute directly.
268
+
269
+ ```
270
+ np = pyimport("numpy")
271
+ matrix = np.array([[1, 2], [3, 4]])
272
+
273
+ push(matrix.shape) => (2, 2)
274
+ push(matrix.T)
275
+ push(pyimport("math").pi) => 3.141592653589793
276
+ ```
277
+
278
+ Reserved words such as `pi`, `sin`, `cos` and `tan` are treated as ordinary
279
+ names when they follow a `.`, so `math.pi` and `np.sin(x)` both work.
280
+
281
+ ### The `@` operator
282
+
283
+ `@` is matrix multiplication, passed straight through to Python's `__matmul__`.
284
+
285
+ ```
286
+ np = pyimport("numpy")
287
+ a = np.array([[1, 2], [3, 4]])
288
+ push(a @ a) => [[ 7 10]
289
+ [15 22]]
290
+ ```
291
+
292
+ It binds at the same level as `*`, so `x @ w + b` multiplies before it adds.
293
+
294
+ ### Why this works everywhere else too
295
+
296
+ BrittainScript values are native Python objects, so once a Python object is in
297
+ a variable, the rest of the language already applies to it — arithmetic,
298
+ indexing, slicing, comparison and `for` loops all use Python's own behaviour:
299
+
300
+ ```
301
+ np = pyimport("numpy")
302
+ values = np.array([10, 20, 30, 40])
303
+
304
+ push(values * 2)
305
+ push(values[1])
306
+ push(values[1:3])
307
+ for value in values:
308
+ push(value)
309
+ end
310
+ ```
311
+
312
+ ### A worked example
313
+
314
+ `examples/torch_demo.bs` trains a small linear model with PyTorch, including a
315
+ hand-written SGD loop driven by autograd. Run it with:
316
+
317
+ ```
318
+ python3 run.py examples/torch_demo.bs
319
+ ```
320
+
321
+ It prints a message and stops if `torch` is not installed.
322
+
323
+ ### A note on scope
324
+
325
+ `pyimport` gives a script the whole Python environment — including `os`,
326
+ `subprocess` and `shutil`. That is the expected trade-off for a scripting
327
+ language FFI and is the same power a Python script has, but it does mean a
328
+ `.bs` file can do anything the Python interpreter running it can do. Treat
329
+ untrusted BrittainScript the way you would treat untrusted Python.
330
+
331
+ ---
332
+
221
333
  ## Test Files
222
334
 
223
335
  There are two standalone test suites in `TestFiles/`. These are self-contained and independent from the main interpreter — they were used to prototype the lexer and parser separately.
@@ -8,10 +8,20 @@ brittainscript.egg-info/entry_points.txt
8
8
  brittainscript.egg-info/requires.txt
9
9
  brittainscript.egg-info/top_level.txt
10
10
  core/__init__.py
11
+ core/gui_backend.py
11
12
  core/lexer.py
12
13
  core/main.py
13
14
  core/parser.py
14
15
  core/parsetab.py
15
16
  libs/__init__.py
16
17
  libs/convert.bs
17
- libs/math.bs
18
+ libs/datetime.bs
19
+ libs/gui.bs
20
+ libs/io.bs
21
+ libs/math.bs
22
+ libs/terminal.bs
23
+ tests/test_datetime_builtin.py
24
+ tests/test_gui_builtins.py
25
+ tests/test_operator_precedence.py
26
+ tests/test_parser_builtins.py
27
+ tests/test_python_bridge.py