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 +1 -1
- shell_lite/lexer.py +48 -12
- shell_lite/main.py +1 -1
- shell_lite/parser_gbp.py +26 -13
- shell_lite-0.5.1.dist-info/METADATA +478 -0
- shell_lite-0.5.1.dist-info/RECORD +20 -0
- {shell_lite-0.5.dist-info → shell_lite-0.5.1.dist-info}/WHEEL +1 -1
- {shell_lite-0.5.dist-info → shell_lite-0.5.1.dist-info}/top_level.txt +0 -1
- shell_lite-0.5.dist-info/METADATA +0 -93
- shell_lite-0.5.dist-info/RECORD +0 -33
- tests/__init__.py +0 -1
- tests/benchmark_driver.py +0 -43
- tests/compare_parsers.py +0 -31
- tests/debug_jit.py +0 -49
- tests/generate_actual_graph.py +0 -84
- tests/generate_perf_graph.py +0 -68
- tests/generate_runtime_graph.py +0 -58
- tests/run_jit.py +0 -70
- tests/test_gbp_standalone.py +0 -37
- tests/test_interpreter.py +0 -8
- tests/test_lexer.py +0 -8
- tests/test_parser.py +0 -8
- tests/test_stdlib.py +0 -8
- {shell_lite-0.5.dist-info → shell_lite-0.5.1.dist-info}/LICENSE +0 -0
- {shell_lite-0.5.dist-info → shell_lite-0.5.1.dist-info}/entry_points.txt +0 -0
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.
|
|
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.
|
|
31
|
-
|
|
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
|
-
|
|
34
|
-
self.indent_stack
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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.
|
|
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)
|
|
25
|
+
[]()
|
|
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,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
|
-
|
shell_lite-0.5.dist-info/RECORD
DELETED
|
@@ -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()
|
tests/generate_actual_graph.py
DELETED
|
@@ -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()
|
tests/generate_perf_graph.py
DELETED
|
@@ -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()
|
tests/generate_runtime_graph.py
DELETED
|
@@ -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()
|
tests/test_gbp_standalone.py
DELETED
|
@@ -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
tests/test_lexer.py
DELETED
tests/test_parser.py
DELETED
tests/test_stdlib.py
DELETED
|
File without changes
|
|
File without changes
|