shell-lite 0.5__py3-none-any.whl → 0.5.1__py3-none-any.whl

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.
shell_lite/interpreter.py CHANGED
@@ -1502,7 +1502,7 @@ class Interpreter:
1502
1502
  self.wfile.write(str(e).encode())
1503
1503
  except: pass
1504
1504
  server = ReusableHTTPServer(('0.0.0.0', port_val), ShellLiteHandler)
1505
- print(f"\n ShellLite Server v0.04.6.8 is running!")
1505
+ print(f"\n ShellLite Server v0.5.1 is running!")
1506
1506
  print(f" \u001b[1;36m➜\u001b[0m Local: \u001b[1;4;36mhttp://localhost:{port_val}/\u001b[0m\n")
1507
1507
  try: server.serve_forever()
1508
1508
  except KeyboardInterrupt:
shell_lite/lexer.py CHANGED
@@ -15,6 +15,8 @@ class Lexer:
15
15
  self.current_char_index = 0
16
16
  self.line_number = 1
17
17
  self.indent_stack = [0]
18
+ self.bracket_depth = 0
19
+
18
20
  def tokenize(self) -> List[Token]:
19
21
  source = self._remove_multiline_comments(self.source_code)
20
22
  lines = source.split('\n')
@@ -27,21 +29,49 @@ class Lexer:
27
29
  if stripped_line.startswith('#'):
28
30
  continue
29
31
  if indent_level > self.indent_stack[-1]:
30
- self.indent_stack.append(indent_level)
31
- self.tokens.append(Token('INDENT', '', self.line_number, indent_level + 1))
32
+ if self.bracket_depth == 0:
33
+ self.indent_stack.append(indent_level)
34
+ self.tokens.append(Token('INDENT', '', self.line_number, indent_level + 1))
32
35
  elif indent_level < self.indent_stack[-1]:
33
- while indent_level < self.indent_stack[-1]:
34
- self.indent_stack.pop()
35
- self.tokens.append(Token('DEDENT', '', self.line_number, indent_level + 1))
36
- if indent_level != self.indent_stack[-1]:
37
- raise IndentationError(f"Unindent does not match any outer indentation level on line {self.line_number}")
36
+ if self.bracket_depth == 0:
37
+ while indent_level < self.indent_stack[-1]:
38
+ self.indent_stack.pop()
39
+ self.tokens.append(Token('DEDENT', '', self.line_number, indent_level + 1))
40
+ if indent_level != self.indent_stack[-1]:
41
+ raise IndentationError(f"Unindent does not match any outer indentation level on line {self.line_number}")
38
42
  self.tokenize_line(stripped_line, indent_level + 1)
39
- self.tokens.append(Token('NEWLINE', '', self.line_number, len(line) + 1))
43
+ if self.bracket_depth == 0:
44
+ self.tokens.append(Token('NEWLINE', '', self.line_number, len(line) + 1))
40
45
  while len(self.indent_stack) > 1:
41
46
  self.indent_stack.pop()
42
47
  self.tokens.append(Token('DEDENT', '', self.line_number, 1))
43
48
  self.tokens.append(Token('EOF', '', self.line_number, 1))
49
+ # Post-process: Convert BEGIN/END to INDENT/DEDENT
50
+ self.tokens = self._convert_begin_end(self.tokens)
44
51
  return self.tokens
52
+
53
+ def _convert_begin_end(self, tokens: List[Token]) -> List[Token]:
54
+ """Convert BEGIN/END keywords to INDENT/DEDENT for uniform parsing."""
55
+ result = []
56
+ i = 0
57
+ while i < len(tokens):
58
+ token = tokens[i]
59
+ if token.type == 'BEGIN':
60
+ # Remove preceding NEWLINE if present (since begin is on its own line)
61
+ if result and result[-1].type == 'NEWLINE':
62
+ result.pop()
63
+ # Just add INDENT (the newline was already there from previous line)
64
+ result.append(Token('INDENT', '', token.line, token.column))
65
+ elif token.type == 'END':
66
+ # Add DEDENT
67
+ result.append(Token('DEDENT', '', token.line, token.column))
68
+ # Skip the NEWLINE after end if present
69
+ if i + 1 < len(tokens) and tokens[i + 1].type == 'NEWLINE':
70
+ i += 1 # Skip the next NEWLINE
71
+ else:
72
+ result.append(token)
73
+ i += 1
74
+ return result
45
75
  def _remove_multiline_comments(self, source: str) -> str:
46
76
  result = []
47
77
  i = 0
@@ -150,6 +180,15 @@ class Lexer:
150
180
  }
151
181
  if char in single_char_tokens:
152
182
  self.tokens.append(Token(single_char_tokens[char], char, self.line_number, current_col))
183
+
184
+ # Track bracket depth here too
185
+ if char in '([{':
186
+ self.bracket_depth += 1
187
+ elif char in ')]}':
188
+ self.bracket_depth -= 1
189
+ if self.bracket_depth < 0:
190
+ self.bracket_depth = 0
191
+
153
192
  pos += 1
154
193
  continue
155
194
  if char.isalpha() or char == '_':
@@ -167,6 +206,7 @@ class Lexer:
167
206
  'check': 'CHECK',
168
207
  'unless': 'UNLESS', 'when': 'WHEN', 'otherwise': 'OTHERWISE',
169
208
  'then': 'THEN', 'do': 'DO',
209
+ 'begin': 'BEGIN', 'end': 'END',
170
210
  'print': 'PRINT', 'say': 'SAY', 'show': 'SAY',
171
211
  'input': 'INPUT', 'ask': 'ASK',
172
212
  'to': 'TO', 'can': 'TO',
@@ -246,8 +286,4 @@ class Lexer:
246
286
  self.tokens.append(Token(token_type, value, self.line_number, current_col))
247
287
  pos += len(value)
248
288
  continue
249
- if char in single_char_tokens:
250
- self.tokens.append(Token(single_char_tokens[char], char, self.line_number, current_col))
251
- pos += 1
252
- continue
253
289
  raise SyntaxError(f"Illegal character '{char}' at line {self.line_number}")
shell_lite/main.py CHANGED
@@ -150,7 +150,7 @@ def install_globally():
150
150
  return
151
151
  ps_cmd = f'$oldPath = [Environment]::GetEnvironmentVariable("Path", "User"); if ($oldPath -notlike "*ShellLite*") {{ [Environment]::SetEnvironmentVariable("Path", "$oldPath;{install_dir}", "User") }}'
152
152
  subprocess.run(["powershell", "-Command", ps_cmd], capture_output=True)
153
- print(f"\n[SUCCESS] ShellLite (v0.04.6.8) is installed!")
153
+ print(f"\n[SUCCESS] ShellLite (v0.5.1) is installed!")
154
154
  print(f"Location: {install_dir}")
155
155
  print("\nIMPORTANT STEP REQUIRED:")
156
156
  print("1. Close ALL open terminal windows (CMD, PowerShell, VS Code).")
shell_lite/parser_gbp.py CHANGED
@@ -11,6 +11,7 @@ class GeoNode:
11
11
  tokens: List[Token] = field(default_factory=list)
12
12
  children: List['GeoNode'] = field(default_factory=list)
13
13
  parent: Optional['GeoNode'] = None
14
+
14
15
  def __repr__(self):
15
16
  return f"GeoNode(line={self.line}, indent={self.indent_level}, head={self.head_token.type})"
16
17
  class GeometricBindingParser:
@@ -39,19 +40,6 @@ class GeometricBindingParser:
39
40
  Phase 1: Scans tokens to build GeoNodes.
40
41
  Phase 2: Links them into a tree based on nesting.
41
42
  """
42
- logical_lines = []
43
- current_line_tokens = []
44
- for token in self.tokens:
45
- if token.type == 'NEWLINE':
46
- if current_line_tokens:
47
- logical_lines.append(current_line_tokens)
48
- current_line_tokens = []
49
- elif token.type in ('INDENT', 'DEDENT', 'EOF'):
50
- pass # logic handled below in a smarter way?
51
- else:
52
- current_line_tokens.append(token)
53
- if current_line_tokens:
54
- logical_lines.append(current_line_tokens)
55
43
  node_stack: List[GeoNode] = [] # The active parents
56
44
  current_tokens_accumulator = []
57
45
  current_node: Optional[GeoNode] = None
@@ -199,6 +187,31 @@ class GeometricBindingParser:
199
187
  values.append(Number(int(t.value) if '.' not in t.value else float(t.value)))
200
188
  elif t.type == 'STRING':
201
189
  values.append(String(t.value))
190
+ elif t.type == 'LBRACKET':
191
+ # Consumed nested list
192
+ depth = 1
193
+ j = i + 1
194
+ elements_tokens = []
195
+ current_elem = []
196
+ while j < len(tokens):
197
+ if tokens[j].type == 'LBRACKET': depth += 1
198
+ elif tokens[j].type == 'RBRACKET': depth -= 1
199
+
200
+ if depth == 0:
201
+ if current_elem: elements_tokens.append(current_elem)
202
+ break
203
+
204
+ if tokens[j].type == 'COMMA' and depth == 1:
205
+ elements_tokens.append(current_elem)
206
+ current_elem = []
207
+ else:
208
+ current_elem.append(tokens[j])
209
+ j += 1
210
+
211
+ # Parse elements
212
+ items = [self.parse_expr_iterative(elem) for elem in elements_tokens if elem]
213
+ values.append(ListVal(items))
214
+ i = j # Advance past list
202
215
  elif t.type == 'ID':
203
216
  if i+1 < len(tokens) and tokens[i+1].type == 'LPAREN':
204
217
  values.append(VarAccess(t.value))
@@ -0,0 +1,478 @@
1
+ Metadata-Version: 2.1
2
+ Name: shell-lite
3
+ Version: 0.5.1
4
+ Summary: A lightweight, English-like scripting language.
5
+ Home-page: https://github.com/Shrey-N/ShellDesk
6
+ Author: Shrey Naithani
7
+ Author-email: Shrey Naithani <contact@shelllite.tech>
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: prompt-toolkit>=3.0.0
15
+
16
+ <img src="assets/logo.png" align="right" width="250" alt="ShellLite Logo" />
17
+
18
+ # ShellLite
19
+
20
+ **The English-Like Programming Language**
21
+
22
+ ShellLite is a modern programming language designed to prioritize human readability. It replaces complex syntax with natural English commands, making software development accessible and maintainable. With version 0.05.0, ShellLite now supports native compilation via LLVM alongside its interpreted mode.
23
+
24
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
25
+ [![Version](https://img.shields.io/badge/version-0.05.0-green.svg)]()
26
+
27
+ ---
28
+
29
+ ## Table of Contents
30
+
31
+ - [Features](#features)
32
+ - [Architecture](#architecture)
33
+ - [Installation](#installation)
34
+ - [Quick Start](#quick-start)
35
+ - [Language Overview](#language-overview)
36
+ - [Compilation](#compilation)
37
+ - [The Three Pillars](#the-three-pillars)
38
+ - [CLI Reference](#cli-reference)
39
+ - [Project Structure](#project-structure)
40
+ - [Documentation](#documentation)
41
+ - [Ecosystem](#ecosystem)
42
+ - [License](#license)
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ | Feature | Description |
49
+ |:--------|:------------|
50
+ | **Natural Syntax** | Write code that reads like English |
51
+ | **Dynamic Typing** | No type declarations required |
52
+ | **Multi-Target Compilation** | Compile to LLVM, JavaScript, or Python |
53
+ | **Python Integration** | Use any Python library via The Bridge |
54
+ | **GUI Framework** | Build desktop apps with The Canvas |
55
+ | **Package Manager** | Manage dependencies with The Universe |
56
+ | **Web Framework** | Built-in HTTP server and routing |
57
+ | **Interactive REPL** | Explore and test code interactively |
58
+
59
+ ---
60
+
61
+ ## Architecture
62
+
63
+ ```mermaid
64
+ flowchart TB
65
+ subgraph Input
66
+ A[Source Code .shl]
67
+ end
68
+
69
+ subgraph Frontend
70
+ B[Lexer]
71
+ C[Parser]
72
+ D[AST]
73
+ end
74
+
75
+ subgraph Backend
76
+ E{Execution Mode}
77
+ F[Interpreter]
78
+ G[LLVM Codegen]
79
+ H[JS Compiler]
80
+ I[Python Transpiler]
81
+ end
82
+
83
+ subgraph Output
84
+ J[Runtime Execution]
85
+ K[Native Binary]
86
+ L[JavaScript File]
87
+ M[Python File]
88
+ end
89
+
90
+ A --> B --> C --> D --> E
91
+ E -->|interpret| F --> J
92
+ E -->|compile llvm| G --> K
93
+ E -->|compile js| H --> L
94
+ E -->|compile python| I --> M
95
+ ```
96
+
97
+ ### Compilation Pipeline
98
+
99
+ ```mermaid
100
+ flowchart LR
101
+ subgraph Lexical Analysis
102
+ A[Source] --> B[Tokens]
103
+ end
104
+
105
+ subgraph Parsing
106
+ B --> C[AST]
107
+ end
108
+
109
+ subgraph Code Generation
110
+ C --> D[LLVM IR]
111
+ D --> E[Optimization]
112
+ E --> F[Native Code]
113
+ end
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Installation
119
+
120
+ ### Via PyPI (Recommended)
121
+
122
+ ```bash
123
+ pip install shell-lite
124
+ ```
125
+
126
+ ### From Source
127
+
128
+ ```bash
129
+ git clone https://github.com/Shrey-N/ShellLite.git
130
+ cd ShellLite
131
+ pip install -e .
132
+ ```
133
+
134
+ ### Windows Installer
135
+
136
+ Download the latest `shl.exe` from the [Releases](https://github.com/Shrey-N/ShellLite/releases) page.
137
+
138
+ ### Verify Installation
139
+
140
+ ```bash
141
+ shl --version
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Quick Start
147
+
148
+ ### Hello World
149
+
150
+ Create a file named `hello.shl`:
151
+
152
+ ```
153
+ say "Hello, World"
154
+ ```
155
+
156
+ Run it:
157
+
158
+ ```bash
159
+ shl hello.shl
160
+ ```
161
+
162
+ ### Interactive REPL
163
+
164
+ ```bash
165
+ shl
166
+ ```
167
+
168
+ ```
169
+ ShellLite REPL - English Syntax
170
+ ========================================
171
+ >>> say "Hello"
172
+ Hello
173
+ >>> 5 + 5
174
+ 10
175
+ >>> exit
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Language Overview
181
+
182
+ ### Type System
183
+
184
+ ```mermaid
185
+ graph TD
186
+ A[ShellLite Types] --> B[Number]
187
+ A --> C[String]
188
+ A --> D[Boolean]
189
+ A --> E[List]
190
+ A --> F[Dictionary]
191
+ A --> G[Function]
192
+ A --> H[Object]
193
+ A --> I[None]
194
+
195
+ B --> B1[Integer]
196
+ B --> B2[Float]
197
+ D --> D1[yes / true]
198
+ D --> D2[no / false]
199
+ ```
200
+
201
+ ### Syntax Examples
202
+
203
+ **Variables and Constants**
204
+ ```
205
+ name = "Alice"
206
+ age = 30
207
+ const PI = 3.14159
208
+ ```
209
+
210
+ **Control Flow**
211
+ ```
212
+ if score > 90
213
+ say "Excellent"
214
+ elif score > 70
215
+ say "Good"
216
+ else
217
+ say "Keep trying"
218
+ ```
219
+
220
+ **Functions**
221
+ ```
222
+ to greet name
223
+ say "Hello, " + name
224
+ give "Greeted " + name
225
+
226
+ result = greet "World"
227
+ ```
228
+
229
+ **Classes**
230
+ ```
231
+ thing Car
232
+ has speed = 0
233
+
234
+ can accelerate amount
235
+ speed += amount
236
+ say "Speed: " + str(speed)
237
+
238
+ my_car = new Car
239
+ my_car.accelerate 50
240
+ ```
241
+
242
+ ### Natural Language Comparisons
243
+
244
+ | Symbol | Natural Form |
245
+ |:------:|:-------------|
246
+ | `==` | `is`, `equals` |
247
+ | `!=` | `is not` |
248
+ | `>` | `is more than` |
249
+ | `<` | `is less than` |
250
+ | `>=` | `is at least` |
251
+ | `<=` | `is at most` |
252
+
253
+ ---
254
+
255
+ ## Compilation
256
+
257
+ ### Compilation Targets
258
+
259
+ ```mermaid
260
+ flowchart LR
261
+ A[script.shl] --> B{shl compile}
262
+ B -->|--target llvm| C[Native Binary]
263
+ B -->|--target js| D[JavaScript]
264
+ B -->|--target python| E[Python]
265
+ ```
266
+
267
+ ### Commands
268
+
269
+ ```bash
270
+ # Compile to native code (default)
271
+ shl compile script.shl
272
+
273
+ # Compile to JavaScript
274
+ shl compile script.shl --target js
275
+
276
+ # Compile to Python
277
+ shl compile script.shl --target python
278
+ ```
279
+
280
+ ### Performance Comparison
281
+
282
+ | Mode | Relative Speed | Use Case |
283
+ |:-----|:---------------|:---------|
284
+ | Interpreted | 1x | Development |
285
+ | Python Compiled | ~1.2x | Integration |
286
+ | JavaScript | ~2-5x | Web deployment |
287
+ | LLVM Native | ~10-50x | Production |
288
+
289
+ ---
290
+
291
+ ## The Three Pillars
292
+
293
+ ShellLite v0.05.0 introduces three major features:
294
+
295
+ ```mermaid
296
+ graph TB
297
+ subgraph "The Bridge"
298
+ A[Python Libraries]
299
+ A1[pandas]
300
+ A2[requests]
301
+ A3[numpy]
302
+ A --> A1
303
+ A --> A2
304
+ A --> A3
305
+ end
306
+
307
+ subgraph "The Canvas"
308
+ B[GUI Framework]
309
+ B1[Windows]
310
+ B2[Dialogs]
311
+ B3[Controls]
312
+ B --> B1
313
+ B --> B2
314
+ B --> B3
315
+ end
316
+
317
+ subgraph "The Universe"
318
+ C[Package Manager]
319
+ C1[Dependencies]
320
+ C2[GitHub Packages]
321
+ C3[shell-lite.toml]
322
+ C --> C1
323
+ C --> C2
324
+ C --> C3
325
+ end
326
+ ```
327
+
328
+ ### The Bridge - Python Integration
329
+
330
+ Import and use any Python library directly:
331
+
332
+ ```
333
+ use "pandas" as pd
334
+ use "requests"
335
+
336
+ data = pd.read_csv("data.csv")
337
+ response = requests.get("https://api.example.com")
338
+ ```
339
+
340
+ ### The Canvas - GUI Applications
341
+
342
+ Build native desktop applications:
343
+
344
+ ```
345
+ app "My App" size 400, 300
346
+
347
+ column
348
+ heading "Welcome"
349
+ button "Click Me" on_click handle_click
350
+
351
+ to handle_click
352
+ alert "Button clicked!"
353
+ ```
354
+
355
+ ### The Universe - Package Management
356
+
357
+ ```bash
358
+ # Initialize project
359
+ shl init
360
+
361
+ # Install dependencies
362
+ shl install
363
+
364
+ # Install from GitHub
365
+ shl get username/repo
366
+ ```
367
+
368
+ **shell-lite.toml**
369
+ ```toml
370
+ [project]
371
+ name = "my-app"
372
+ version = "1.0.0"
373
+
374
+ [dependencies]
375
+ Shrey-N/shl-utils = "main"
376
+ ```
377
+
378
+ ---
379
+
380
+ ## CLI Reference
381
+
382
+ | Command | Description |
383
+ |:--------|:------------|
384
+ | `shl <file.shl>` | Run a ShellLite script |
385
+ | `shl` | Start the interactive REPL |
386
+ | `shl compile <file>` | Compile to native code (LLVM) |
387
+ | `shl compile <file> --target js` | Compile to JavaScript |
388
+ | `shl compile <file> --target python` | Compile to Python |
389
+ | `shl init` | Initialize a new project |
390
+ | `shl install` | Install project dependencies |
391
+ | `shl get <user/repo>` | Install a package from GitHub |
392
+ | `shl fmt <file>` | Format a script |
393
+ | `shl check <file>` | Lint a file (JSON output) |
394
+ | `shl help` | Show help message |
395
+
396
+ ---
397
+
398
+ ## Project Structure
399
+
400
+ ```
401
+ my-project/
402
+ ├── main.shl # Entry point
403
+ ├── shell-lite.toml # Project configuration
404
+ ├── modules/
405
+ │ ├── utils.shl # Utility functions
406
+ │ └── api.shl # API handlers
407
+ ├── tests/
408
+ │ └── test_main.shl # Test files
409
+ └── public/
410
+ └── index.html # Static files (web)
411
+ ```
412
+
413
+ ---
414
+
415
+ ## Documentation
416
+
417
+ ### Language Guide
418
+
419
+ | Chapter | Topic |
420
+ |:--------|:------|
421
+ | [01](docs/01_Getting_Started.md) | Getting Started |
422
+ | [02](docs/02_Language_Basics.md) | Language Basics |
423
+ | [03](docs/03_Control_Flow.md) | Control Flow |
424
+ | [04](docs/04_Data_Structures.md) | Data Structures |
425
+ | [05](docs/05_Functions_and_OOP.md) | Functions and OOP |
426
+ | [06](docs/06_Modules_and_StdLib.md) | Modules and Standard Library |
427
+ | [07](docs/07_System_Mastery.md) | System Mastery |
428
+ | [08](docs/08_Web_Development.md) | Web Development |
429
+
430
+ ### Advanced Topics
431
+
432
+ | Chapter | Topic |
433
+ |:--------|:------|
434
+ | [09](docs/09_Advanced_Features.md) | Advanced Features |
435
+ | [10](docs/10_Compilation_and_Performance.md) | Compilation and Performance |
436
+ | [11](docs/11_Testing_and_Debugging.md) | Testing and Debugging |
437
+ | [12](docs/12_API_Reference.md) | API Reference |
438
+
439
+ ### Guides and Resources
440
+
441
+ | Chapter | Topic |
442
+ |:--------|:------|
443
+ | [13](docs/13_Security_Guide.md) | Security Guide |
444
+ | [14](docs/14_Migration_Guide.md) | Migration Guide |
445
+ | [15](docs/15_Troubleshooting.md) | Troubleshooting |
446
+ | [16](docs/16_Examples_and_Tutorials.md) | Examples and Tutorials |
447
+ | [17](docs/17_Best_Practices.md) | Best Practices |
448
+
449
+ ---
450
+
451
+ ## Ecosystem
452
+
453
+ | Tool | Description | Link |
454
+ |:-----|:------------|:-----|
455
+ | **Book** | Language design, compiler construction, and architecture guide | [Book](https://books2read.com/b/mVpoXM) |
456
+ | **ShellDesk** | Official IDE for ShellLite | [GitHub](https://github.com/Shrey-N/ShellDesk) |
457
+ | **VS Code Extension** | Syntax highlighting and snippets | [Marketplace](https://marketplace.visualstudio.com/items?itemName=ShellLite.shelllite-hello) |
458
+ | **Research Artifact** | Published on Zenodo by CERN | [Zenodo](https://github.com/Shrey-N/ShellDesk) |
459
+
460
+ ---
461
+
462
+ ## Contributing
463
+
464
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to contribute to ShellLite.
465
+
466
+ ## Security
467
+
468
+ See [SECURITY.md](SECURITY.md) for reporting security vulnerabilities.
469
+
470
+ ## License
471
+
472
+ MIT License - See [LICENSE](LICENSE) for details.
473
+
474
+ ---
475
+
476
+ **ShellLite** - Making programming accessible through natural language.
477
+
478
+ Created by Shrey Naithani
@@ -0,0 +1,20 @@
1
+ shell_lite/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
2
+ shell_lite/ast_nodes.py,sha256=W2oefXuRjqnQybR5ZcdPU0qC5gxHZHcotQc3LAVDLM0,6129
3
+ shell_lite/cli.py,sha256=14Kq1ohSXS3p-xdh0DPi7eXskUtSX81huSyGhktoOMA,250
4
+ shell_lite/compiler.py,sha256=t2Imae9h03v3GIIKrCo16qCDDLKSxrpjrp83tv0SzUQ,24982
5
+ shell_lite/interpreter.py,sha256=b2y2f-ric_LkIrXM2Z38xBsO2bCK0fuHzSX434621Lg,75869
6
+ shell_lite/js_compiler.py,sha256=yEGIkkIvHGU7o1htHEqlQr6BE0wL35PtL5PssNld9fc,5606
7
+ shell_lite/lexer.py,sha256=cNLk_N59a7eKQaQp7Mqcnxy1um64-QgtDEi2eAsAWKE,14913
8
+ shell_lite/main.py,sha256=A4Yk97DHCap8Xs7dIsjy0pCkSiuzEnf1vO3gRF8tgSI,19877
9
+ shell_lite/parser.py,sha256=qsR2wQUWjUPXbXgnmv8pmOgfX99lYYH6tpxKH3PEnfQ,88471
10
+ shell_lite/parser_gbp.py,sha256=XRQ3AlNZvcq4nysMafF7rPIIcv_38vPG371vFS4QE-M,10168
11
+ shell_lite/runtime.py,sha256=pSjBeA1dTQ-a94q3FLdv9lqZurdd6MJmfhFGHhOoQEM,16057
12
+ shell_lite/llvm_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ shell_lite/llvm_backend/builder.py,sha256=WjDj65DePu8LPpOpnjfS2XREy9vQt7aySAqRYvBMq5w,1434
14
+ shell_lite/llvm_backend/codegen.py,sha256=sTpYxSdrOOqyjf9lj7TLQ5ZFOUM17RykL1QNeariZZM,15875
15
+ shell_lite-0.5.1.dist-info/LICENSE,sha256=33eziKLPxbqGCqdHtEHAFe1KSOgqc0-jWUQmdgKq85Q,1092
16
+ shell_lite-0.5.1.dist-info/METADATA,sha256=LkCUMAYeDRzm5N9_Q_DDDKQ3hKlSDweisCX4QZfJjq8,10447
17
+ shell_lite-0.5.1.dist-info/WHEEL,sha256=hPN0AlP2dZM_3ZJZWP4WooepkmU9wzjGgCLCeFjkHLA,92
18
+ shell_lite-0.5.1.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
19
+ shell_lite-0.5.1.dist-info/top_level.txt,sha256=hIln5ltrok_Mn3ijlQeqMFF6hHBHCyhzqCO7KL358cg,11
20
+ shell_lite-0.5.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: bdist_wheel (0.46.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,93 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: shell-lite
3
- Version: 0.5
4
- Summary: ShellLite: The English-Like Programming Language with LLVM Backend
5
- Home-page: https://github.com/Shrey-N/ShellDesk
6
- Author: Shrey Naithani
7
- Author-email: mrytshplays@gmail.com
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: llvmlite >=0.40.0
15
- Requires-Dist: colorama
16
- Requires-Dist: prompt-toolkit
17
- Requires-Dist: pygments
18
- Requires-Dist: pyinstaller
19
-
20
- <img src="assets/logo.png" align="right" width="250" alt="ShellLite Logo" />
21
-
22
- # ShellLite: The English-Like Programming Language
23
- # By Shrey Naithani
24
- ShellLite is a modern, interpreted programming language designed to prioritize human readability. It replaces complex syntax with natural English commands, making software development accessible and maintainable.
25
-
26
- ## Version 0.04.0 (Polaris Update)
27
-
28
- This release transforms ShellLite from a scripting tool into a comprehensive platform with three major pillars:
29
- 1. **The Bridge**: Import and use any Python library (pandas, requests, etc.) natively.
30
- 2. **The Canvas**: Build native desktop GUI applications with declarative syntax.
31
- 3. **The Universe**: Integrated package management for project dependencies.
32
-
33
- ## Installation
34
-
35
- ### Via PyPI (Recommended)
36
- You can install ShellLite directly from PyPI:
37
- ```bash
38
- pip install shell-lite
39
- ```
40
-
41
- ### Windows Installer
42
- Download the latest `shl.exe` from the Releases page.
43
-
44
- ## Compilation
45
-
46
- To compile ShellLite code to native machine code (LLVM IR):
47
-
48
- ```bash
49
- shl compile script.shl
50
- ```
51
-
52
- ## Quick Start
53
-
54
- ### 1. Hello World
55
- Save this as `hello.shl`:
56
- ```shell-lite
57
- say "Hello, World"
58
- ```
59
- Run it:
60
- ```bash
61
- shl hello.shl
62
- ```
63
- ## Project Management
64
-
65
- Initialize a new project:
66
- ```bash
67
- shl init
68
- ```
69
-
70
- Install dependencies defined in `shell-lite.toml`:
71
- ```bash
72
- shl install
73
- ```
74
-
75
- ## Ecosystem & Tools
76
-
77
- | Tool | Description | Link |
78
- | :--- | :--- | :--- |
79
- | **Book** | teaches cognitive friendly language design, controlled natural languages, compiler construction, forgiving parsing, FFI bridging, performance tuning, and provides full grammar, implementation, and architecture. | [Book](https://books2read.com/b/mVpoXM) |
80
- | **Research Artifact** | Published on Zenodo By CERN | [GitHub](https://github.com/Shrey-N/ShellDesk) |
81
- | **ShellDesk** | The official IDE for ShellLite. | [GitHub](https://github.com/Shrey-N/ShellDesk) |
82
- | **VS Code Extension** | Syntax highlighting and snippets. | [Marketplace](https://marketplace.visualstudio.com/items?itemName=ShellLite.shelllite-hello) / [OpenVSX](https://open-vsx.org/extension/shelllite/shelllite-hello) |
83
- | **Website** | Official website source code. | [GitHub](https://github.com/Shrey-N/ShellLite-Website) |
84
-
85
- ## Documentation
86
-
87
- Full documentation is available directly in this repository:
88
- - [**Language Guide**](https://github.com/Shrey-N/ShellLite)
89
- - [**Examples**](https://github.com/Shrey-N/ShellLite/tree/main/examples)
90
-
91
- License: MIT
92
- Made by Shrey Naithani
93
-
@@ -1,33 +0,0 @@
1
- shell_lite/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
2
- shell_lite/ast_nodes.py,sha256=W2oefXuRjqnQybR5ZcdPU0qC5gxHZHcotQc3LAVDLM0,6129
3
- shell_lite/cli.py,sha256=14Kq1ohSXS3p-xdh0DPi7eXskUtSX81huSyGhktoOMA,250
4
- shell_lite/compiler.py,sha256=t2Imae9h03v3GIIKrCo16qCDDLKSxrpjrp83tv0SzUQ,24982
5
- shell_lite/interpreter.py,sha256=-b4Oc-7SMeozbGo7-KQXQ-ip0t2VaG9naz68LiwN27U,75872
6
- shell_lite/js_compiler.py,sha256=yEGIkkIvHGU7o1htHEqlQr6BE0wL35PtL5PssNld9fc,5606
7
- shell_lite/lexer.py,sha256=JGqh89LQDCznUPo0YeZp4rm4B8SpshfIYfXdoXOy1Yc,13339
8
- shell_lite/main.py,sha256=9Up-AcE-J0VxMFai8iJ05ouGpBTCFN0AO9b6q7PVUZE,19880
9
- shell_lite/parser.py,sha256=qsR2wQUWjUPXbXgnmv8pmOgfX99lYYH6tpxKH3PEnfQ,88471
10
- shell_lite/parser_gbp.py,sha256=gvITN-5kgZa5fhH5jKITJuK2Rp9I7j8sACKQfppct3g,9640
11
- shell_lite/runtime.py,sha256=pSjBeA1dTQ-a94q3FLdv9lqZurdd6MJmfhFGHhOoQEM,16057
12
- shell_lite/llvm_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- shell_lite/llvm_backend/builder.py,sha256=WjDj65DePu8LPpOpnjfS2XREy9vQt7aySAqRYvBMq5w,1434
14
- shell_lite/llvm_backend/codegen.py,sha256=sTpYxSdrOOqyjf9lj7TLQ5ZFOUM17RykL1QNeariZZM,15875
15
- tests/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
16
- tests/benchmark_driver.py,sha256=LBnreweO1x6K1-sw1Xf_vF8YogBqsKvIYBLuuSQUlLg,1526
17
- tests/compare_parsers.py,sha256=cC4aiKOQFmwcAYS2gcprjIX8rvvwciEN6ZL24YAvAuI,1113
18
- tests/debug_jit.py,sha256=ghJEnTc2eMqVGSexFyvoQEsGeuvixiUZKG7qZ1QX4Do,1877
19
- tests/generate_actual_graph.py,sha256=XLaG7a18avGlHvr-nbAMS6EQdTtmUKvwqjMwN2da08I,3329
20
- tests/generate_perf_graph.py,sha256=6xkDJvan3M6AzyHxo_BluBHNdXRKCTMq5UkLNRp_ikA,2621
21
- tests/generate_runtime_graph.py,sha256=GIcP8CIWLbrlHe-49ZfM6SOmuwcGsXd4x5A1F-I0d5g,2236
22
- tests/run_jit.py,sha256=T7QhoKWitoBNBWEU-chKCLXiuohbwb4uHazvUdljIYE,2358
23
- tests/test_gbp_standalone.py,sha256=p4EdLHLSPr7YwcY2ZcFeOTMeca-ICyIxlCthNbthagg,986
24
- tests/test_interpreter.py,sha256=04mYgjAw9DBbzM99rrEbRElCKamuJZDLnm2JdswGiw8,204
25
- tests/test_lexer.py,sha256=XTV0ixB8wSQ6RZpOpxa1Q8etkDKDMbv6mflN4IHAKzw,206
26
- tests/test_parser.py,sha256=c7DPLC7i7uCikKMJ099VJEYQzqesVZMSQ5ufNCTta8c,213
27
- tests/test_stdlib.py,sha256=wtCIeNkrnEp6v9DO1wMA3HPb1ANBzcveVKwLFJV81ho,204
28
- shell_lite-0.5.dist-info/LICENSE,sha256=33eziKLPxbqGCqdHtEHAFe1KSOgqc0-jWUQmdgKq85Q,1092
29
- shell_lite-0.5.dist-info/METADATA,sha256=Hx_YfK8NNMCuZr7rhfN1kJNLXl0buOYaN3HWSP4b-c0,3186
30
- shell_lite-0.5.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
31
- shell_lite-0.5.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
32
- shell_lite-0.5.dist-info/top_level.txt,sha256=LzIh1SJEY6HL6ZnmzrKTe2zGpFHgUgjV5XscPHHlu3Q,17
33
- shell_lite-0.5.dist-info/RECORD,,
tests/__init__.py DELETED
@@ -1 +0,0 @@
1
-
tests/benchmark_driver.py DELETED
@@ -1,43 +0,0 @@
1
- import os
2
- import time
3
- import subprocess
4
- import sys
5
- SHL_CMD = ["python", "shell_lite/main.py"]
6
- def run_benchmark():
7
- print("Generating LLVM IR...")
8
- subprocess.run(SHL_CMD + ["llvm", "tests/runtime_benchmark.shl"], check=True)
9
- print("Compiling with Clang...")
10
- subprocess.run(["clang", "tests/runtime_benchmark.ll", "-o", "tests/runtime_benchmark.exe", "-O3"], check=True)
11
- print("\n[Running Native Executable...]")
12
- start = time.perf_counter()
13
- subprocess.run(["tests/runtime_benchmark.exe"], check=True)
14
- native_time = time.perf_counter() - start
15
- print(f"Native Time: {native_time:.4f}s")
16
- print("\n[Running Interpreter (GBP)...]")
17
- env = os.environ.copy()
18
- env["USE_GBP"] = "1"
19
- start = time.perf_counter()
20
- subprocess.run(SHL_CMD + ["run", "tests/runtime_benchmark.shl"], env=env, check=True)
21
- interp_time = time.perf_counter() - start
22
- print(f"Interpreter Time: {interp_time:.4f}s")
23
- print("\n[Running Python Equivalent...]")
24
- py_code = """
25
- i = 0
26
- sum = 0
27
- count = 100000000
28
- while i < count:
29
- sum = sum + 1
30
- i = i + 1
31
- print("Done")
32
- print(sum)
33
- """
34
- start = time.perf_counter()
35
- exec(py_code)
36
- py_time = time.perf_counter() - start
37
- print(f"Python Time: {py_time:.4f}s")
38
- print("\n" + "="*30)
39
- print(f"Native Speedup vs Interpreter: {interp_time/native_time:.2f}x")
40
- print(f"Native Speedup vs Python: {py_time/native_time:.2f}x")
41
- print("="*30)
42
- if __name__ == "__main__":
43
- run_benchmark()
tests/compare_parsers.py DELETED
@@ -1,31 +0,0 @@
1
- import sys
2
- import os
3
- import time
4
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
5
- from shell_lite.lexer import Lexer
6
- from shell_lite.parser import Parser
7
- from shell_lite.parser_gbp import GeometricBindingParser
8
- def benchmark(filename):
9
- with open(filename, 'r') as f:
10
- source = f.read()
11
- long_source = source * 500
12
- print(f"Benchmarking on {len(long_source)} chars of code...")
13
- lexer = Lexer(long_source)
14
- tokens = lexer.tokenize()
15
- tokens_copy = list(tokens)
16
- start = time.perf_counter()
17
- p_old = Parser(list(tokens)) # fresh copy? Parser consumes? yes
18
- ast_old = p_old.parse()
19
- end = time.perf_counter()
20
- t_old = end - start
21
- print(f"Recursive Descent: {t_old:.4f}s")
22
- start = time.perf_counter()
23
- p_new = GeometricBindingParser(list(tokens))
24
- ast_new = p_new.parse()
25
- end = time.perf_counter()
26
- t_new = end - start
27
- print(f"Geometric-Binding: {t_new:.4f}s")
28
- diff = t_old / t_new if t_new > 0 else 0
29
- print(f"Speedup: {diff:.2f}x")
30
- if __name__ == "__main__":
31
- benchmark("tests/benchmark.shl")
tests/debug_jit.py DELETED
@@ -1,49 +0,0 @@
1
- import llvmlite.binding as llvm
2
- import sys
3
- def debug():
4
- try:
5
- llvm.initialize()
6
- llvm.initialize_native_target()
7
- llvm.initialize_native_asmprinter()
8
- print("LLVM Initialized.")
9
- except Exception as e:
10
- print(f"Init Failed: {e}")
11
- return
12
- print("Available in llvm.binding:")
13
- ops = [x for x in dir(llvm) if 'create' in x or 'jit' in x.lower() or 'engine' in x.lower()]
14
- print(ops)
15
- try:
16
- mod = llvm.parse_assembly('define i32 @answer() { ret i32 42 }')
17
- mod.verify()
18
- print("Module parsed.")
19
- target = llvm.Target.from_default_triple()
20
- target_machine = target.create_target_machine()
21
- engine = None
22
- if hasattr(llvm, 'create_mcjit_compiler'):
23
- print("Attempting MCJIT...")
24
- try:
25
- engine = llvm.create_mcjit_compiler(mod, target_machine)
26
- print("MCJIT Created!")
27
- except Exception as e:
28
- print(f"MCJIT Failed: {e}")
29
- if not engine and hasattr(llvm, 'create_execution_engine'):
30
- print("Attempting create_execution_engine...")
31
- try:
32
- engine = llvm.create_execution_engine()
33
- engine.add_module(mod)
34
- print("ExecEngine Created!")
35
- except Exception as e:
36
- print(f"ExecEngine Failed: {e}")
37
- if engine:
38
- engine.finalize_object()
39
- print("Engine Finalized.")
40
- addr = engine.get_function_address("answer")
41
- print(f"Function Address: {addr}")
42
- import ctypes
43
- cfunc = ctypes.CFUNCTYPE(ctypes.c_int)(addr)
44
- res = cfunc()
45
- print(f"Result: {res}")
46
- except Exception as e:
47
- print(f"Module/Engine Error: {e}")
48
- if __name__ == "__main__":
49
- debug()
@@ -1,84 +0,0 @@
1
- import sys
2
- import os
3
- import time
4
- import matplotlib.pyplot as plt
5
- import subprocess
6
- import llvmlite.binding as llvm
7
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
8
- try:
9
- from tests.run_jit import compile_and_run_jit
10
- except ImportError:
11
- sys.path.append(os.path.join(os.path.dirname(__file__)))
12
- from run_jit import compile_and_run_jit
13
- def run_benchmark():
14
- counts = [1000000, 10000000, 50000000, 100000000, 200000000]
15
- t_interp = []
16
- t_python = []
17
- t_llvm = []
18
- print("Running Massive Runtime Benchmark...")
19
- for n in counts:
20
- print(f"\n--- n = {n} ---")
21
- if n <= 100000: # Reduced limit for massive scale run
22
- shl_code = f"i = 0\nwhile i < {n}:\n i = i + 1\n"
23
- shl_file = f"tests/temp_{n}.shl"
24
- with open(shl_file, "w") as f: f.write(shl_code)
25
- env = os.environ.copy()
26
- env["USE_GBP"] = "1"
27
- start = time.perf_counter()
28
- try:
29
- subprocess.run(["python", "shell_lite/main.py", "run", shl_file], env=env, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
30
- dur = time.perf_counter() - start
31
- except subprocess.CalledProcessError as e:
32
- print(f"Interp failed: {e.stderr.decode()}")
33
- dur = None
34
- except Exception as e:
35
- print(f"Interp failed: {e}")
36
- dur = None
37
- t_interp.append(dur)
38
- if os.path.exists(shl_file): os.remove(shl_file)
39
- if dur is not None:
40
- print(f"Interpreter: {dur:.4f}s")
41
- else:
42
- print("Interpreter: Failed")
43
- else:
44
- t_interp.append(None)
45
- print("Interpreter: Skipped (Too Slow)")
46
- start = time.perf_counter()
47
- i = 0
48
- while i < n:
49
- i += 1
50
- dur = time.perf_counter() - start
51
- t_python.append(dur)
52
- print(f"Python: {dur:.6f}s")
53
- jit_code = f"""
54
- i = 0
55
- count = {n}
56
- while i < count:
57
- i = i + 1
58
- """
59
- try:
60
- _, dur, _ = compile_and_run_jit(jit_code)
61
- if dur < 1e-7: dur = 1e-7
62
- t_llvm.append(dur)
63
- print(f"LLVM JIT: {dur:.8f}s")
64
- except Exception as e:
65
- print(f"JIT Failed: {e}")
66
- t_llvm.append(None)
67
- plt.figure(figsize=(10, 6))
68
- x_interp = [x for x, y in zip(counts, t_interp) if y is not None]
69
- y_interp = [y for y in t_interp if y is not None]
70
- if x_interp:
71
- plt.plot(x_interp, y_interp, label='ShellLite Interpreter', marker='o', color='orange')
72
- plt.plot(counts, t_python, label='Python Native', marker='s', color='green')
73
- plt.plot(counts, t_llvm, label='LLVM JIT', marker='^', color='purple', linestyle='-')
74
- plt.xlabel('Iterations')
75
- plt.ylabel('Time (seconds)')
76
- plt.title('GBP+LLVM Runtime Performance (Massive Scale)')
77
- plt.yscale('log')
78
- plt.legend()
79
- plt.grid(True, which="both", ls="-", alpha=0.2)
80
- output_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'benchmark_final.png'))
81
- plt.savefig(output_path)
82
- print(f"Graph saved to {output_path}")
83
- if __name__ == "__main__":
84
- run_benchmark()
@@ -1,68 +0,0 @@
1
- import sys
2
- import os
3
- import time
4
- import matplotlib.pyplot as plt
5
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
6
- from shell_lite.lexer import Lexer
7
- from shell_lite.parser import Parser
8
- from shell_lite.parser_gbp import GeometricBindingParser
9
- HAS_LLVM = False
10
- try:
11
- from shell_lite.llvm_backend.codegen import LLVMCompiler
12
- HAS_LLVM = True
13
- except ImportError:
14
- print("LLVM backend (llvmlite) not found. Skipping LLVM benchmark.")
15
- def generate_large_file(lines=1000):
16
- code = "x = 0\n"
17
- for i in range(lines):
18
- code += f"if x < {i}:\n"
19
- code += f" x = x + 1\n"
20
- return code
21
- def run_benchmark():
22
- sizes = [1000, 5000, 10000, 20000, 50000]
23
- times_old = []
24
- times_gbp = []
25
- times_py = []
26
- times_llvm = []
27
- for size in sizes:
28
- print(f"Benchmarking size: {size} lines...")
29
- source_shl = generate_large_file(size)
30
- source_py = source_shl.replace("x = x + 1", "x += 1")
31
- start = time.perf_counter()
32
- l = Lexer(source_shl)
33
- toks = l.tokenize()
34
- Parser(toks).parse()
35
- times_old.append(time.perf_counter() - start)
36
- start = time.perf_counter()
37
- l = Lexer(source_shl)
38
- toks = l.tokenize()
39
- GeometricBindingParser(toks).parse()
40
- times_gbp.append(time.perf_counter() - start)
41
- start = time.perf_counter()
42
- compile(source_py, '<string>', 'exec')
43
- times_py.append(time.perf_counter() - start)
44
- start = time.perf_counter()
45
- if HAS_LLVM:
46
- l = Lexer(source_shl)
47
- toks = l.tokenize()
48
- ast = GeometricBindingParser(toks).parse()
49
- LLVMCompiler().compile(ast)
50
- times_llvm.append(time.perf_counter() - start)
51
- else:
52
- times_llvm.append(0)
53
- plt.figure(figsize=(10, 6))
54
- plt.plot(sizes, times_old, label='Old Parser', marker='o', color='red')
55
- plt.plot(sizes, times_gbp, label='GBP Parser', marker='s', color='blue')
56
- plt.plot(sizes, times_py, label='Python Native', marker='^', color='green')
57
- if HAS_LLVM and any(times_llvm):
58
- plt.plot(sizes, times_llvm, label='LLVM Compile (via GBP)', marker='x', color='purple', linestyle='--')
59
- plt.xlabel('Lines of Code')
60
- plt.ylabel('Time (seconds)')
61
- plt.title('Parsing/Compilation Speed vs Code Size')
62
- plt.legend()
63
- plt.grid(True)
64
- output_path = os.path.join(os.path.dirname(__file__), 'benchmark_scaling.png')
65
- plt.savefig(output_path)
66
- print(f"Graph saved to {output_path}")
67
- if __name__ == "__main__":
68
- run_benchmark()
@@ -1,58 +0,0 @@
1
- import sys
2
- import os
3
- import time
4
- import matplotlib.pyplot as plt
5
- import subprocess
6
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
7
- def run_benchmark():
8
- iterations = 1000000 # 1 Million
9
- print(f"Benchmarking Runtime (Count: {iterations})...")
10
- shl_code = f"""
11
- i = 0
12
- while i < {iterations}:
13
- i = i + 1
14
- """
15
- shl_file = "tests/temp_loop.shl"
16
- with open(shl_file, "w") as f:
17
- f.write(shl_code)
18
- env = os.environ.copy()
19
- env["USE_GBP"] = "1"
20
- start = time.perf_counter()
21
- try:
22
- subprocess.run(["python", "shell_lite/main.py", "run", shl_file], env=env, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
23
- except subprocess.CalledProcessError as e:
24
- print(f"Interpreter Crash:\n{e.stderr.decode()}")
25
- t_interp = 10.0 # Dummy
26
- else:
27
- t_interp = time.perf_counter() - start
28
- print(f"Interpreter: {t_interp:.4f}s")
29
- start = time.perf_counter()
30
- i = 0
31
- while i < iterations:
32
- i = i + 1
33
- t_python = time.perf_counter() - start
34
- print(f"Python: {t_python:.4f}s")
35
- t_llvm_est = t_python / 20.0
36
- print(f"LLVM (Est): {t_llvm_est:.4f}s")
37
- labels = ['ShellLite Interpreter', 'Python Native', 'LLVM Native (Projected)']
38
- times = [t_interp, t_python, t_llvm_est]
39
- colors = ['orange', 'green', 'purple']
40
- plt.figure(figsize=(10, 6))
41
- bars = plt.bar(labels, times, color=colors)
42
- plt.ylabel('Execution Time (seconds)')
43
- plt.title(f'Runtime Speed Comparison ({iterations} Iterations)')
44
- plt.yscale('log') # Log scale because difference is massive
45
- for bar in bars:
46
- height = bar.get_height()
47
- plt.text(bar.get_x() + bar.get_width()/2., height,
48
- f'{height:.4f}s',
49
- ha='center', va='bottom')
50
- plt.figtext(0.5, 0.01,
51
- "Note: Logarithmic Scale used due to massive speed difference.",
52
- ha="center", fontsize=10)
53
- output_path = os.path.join(os.path.dirname(__file__), 'benchmark_runtime.png')
54
- plt.savefig(output_path)
55
- print(f"Graph saved to {output_path}")
56
- if os.path.exists(shl_file): os.remove(shl_file)
57
- if __name__ == "__main__":
58
- run_benchmark()
tests/run_jit.py DELETED
@@ -1,70 +0,0 @@
1
- import sys
2
- import os
3
- import time
4
- import ctypes
5
- import llvmlite.binding as llvm
6
- try:
7
- from llvmlite.binding.orcjit import create_lljit_compiler, JITLibraryBuilder
8
- except ImportError:
9
- import llvmlite.binding.orcjit as orc
10
- create_lljit_compiler = orc.create_lljit_compiler
11
- JITLibraryBuilder = orc.JITLibraryBuilder
12
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
13
- from shell_lite.lexer import Lexer
14
- from shell_lite.parser_gbp import GeometricBindingParser
15
- from shell_lite.llvm_backend.codegen import LLVMCompiler
16
- def compile_and_run_jit(source_code):
17
- llvm.initialize_native_target()
18
- llvm.initialize_native_asmprinter()
19
- start_compile = time.perf_counter()
20
- lexer = Lexer(source_code)
21
- tokens = lexer.tokenize()
22
- ast = GeometricBindingParser(tokens).parse()
23
- compiler = LLVMCompiler()
24
- ir_module = compiler.compile(ast)
25
- llvm_ir = str(ir_module)
26
- start_jit = time.perf_counter()
27
- lljit = create_lljit_compiler()
28
- builder = JITLibraryBuilder()
29
- builder.add_ir(llvm_ir)
30
- tracker = builder.link(lljit, "shell_lite_lib")
31
- try:
32
- addr = tracker["main"]
33
- except KeyError:
34
- try:
35
- addr = tracker["_main"]
36
- except KeyError:
37
- print("Error: Could not find 'main' symbol.")
38
- return 0, 0, -1
39
- jit_time = time.perf_counter() - start_jit
40
- cfunc = ctypes.CFUNCTYPE(ctypes.c_int)(addr)
41
- start_run = time.perf_counter()
42
- res = cfunc()
43
- run_time = time.perf_counter() - start_run
44
- return start_jit - start_compile, run_time, res
45
- if __name__ == "__main__":
46
- code = """
47
- sum = 0
48
- i = 0
49
- count = 10000000
50
- while i < count:
51
- sum = sum + 1
52
- i = i + 1
53
- print sum
54
- """
55
- print("Running JIT Speed Test (10M iterations)...")
56
- try:
57
- c_time, r_time, res = compile_and_run_jit(code)
58
- print(f"Result: {res}")
59
- print(f"JIT Exec Time: {r_time:.6f}s")
60
- start_py = time.perf_counter()
61
- s, i, c = 0, 0, 10000000
62
- while i < c:
63
- s += 1
64
- i += 1
65
- py_time = time.perf_counter() - start_py
66
- print(f"Python Exec: {py_time:.6f}s")
67
- print(f"Speedup: {py_time / r_time:.2f}x")
68
- except Exception as e:
69
- import traceback
70
- traceback.print_exc()
@@ -1,37 +0,0 @@
1
- import sys
2
- import os
3
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
4
- from shell_lite.lexer import Lexer
5
- from shell_lite.parser_gbp import GeometricBindingParser
6
- def test_gbp(code, name):
7
- print(f"--- Testing {name} ---")
8
- print(f"Code:\n{code}")
9
- lexer = Lexer(code)
10
- tokens = lexer.tokenize()
11
- parser = GeometricBindingParser(tokens)
12
- parser.topology_scan()
13
- print("\n[Phase 1] Topology Roots:")
14
- for node in parser.root_nodes:
15
- print(f" {node}")
16
- for child in node.children:
17
- print(f" -> {child}")
18
- ast = parser.parse()
19
- print("\n[Phase 2] AST:")
20
- for node in ast:
21
- print(f" {node}")
22
- print("------------------------\n")
23
- if __name__ == "__main__":
24
- code1 = """
25
- x = 10
26
- if x > 5:
27
- print x
28
- y = x + 1
29
- """
30
- test_gbp(code1, "Basic If")
31
- code2 = """
32
- to greet name:
33
- print "Hello"
34
- print name
35
- greet "Bob"
36
- """
37
- test_gbp(code2, "Function Def")
tests/test_interpreter.py DELETED
@@ -1,8 +0,0 @@
1
- import unittest
2
- class TestInterpreter(unittest.TestCase):
3
- def test_visit_number(self):
4
- pass
5
- def test_visit_binop(self):
6
- pass
7
- if __name__ == '__main__':
8
- unittest.main()
tests/test_lexer.py DELETED
@@ -1,8 +0,0 @@
1
- import unittest
2
- class TestLexer(unittest.TestCase):
3
- def test_lexer_initialization(self):
4
- pass
5
- def test_make_tokens(self):
6
- pass
7
- if __name__ == '__main__':
8
- unittest.main()
tests/test_parser.py DELETED
@@ -1,8 +0,0 @@
1
- import unittest
2
- class TestParser(unittest.TestCase):
3
- def test_parser_initialization(self):
4
- pass
5
- def test_parse_expression(self):
6
- pass
7
- if __name__ == '__main__':
8
- unittest.main()
tests/test_stdlib.py DELETED
@@ -1,8 +0,0 @@
1
- import unittest
2
- class TestStdLib(unittest.TestCase):
3
- def test_print_function(self):
4
- pass
5
- def test_input_function(self):
6
- pass
7
- if __name__ == '__main__':
8
- unittest.main()