solpl 2.0.0__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
solpl-2.1.0/PKG-INFO ADDED
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: solpl
3
+ Version: 2.1.0
4
+ Summary: Sol Programming Language Interpreter
5
+ Requires-Python: >=3.7
6
+ License-File: LICENSE
7
+ Dynamic: license-file
@@ -0,0 +1,15 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "solpl"
7
+ version = "2.1.0"
8
+ description = "Sol Programming Language Interpreter"
9
+ requires-python = ">=3.7"
10
+
11
+ [project.scripts]
12
+ solpl = "sol:main"
13
+
14
+ [tool.setuptools]
15
+ py-modules = ["sol"]
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: solpl
3
+ Version: 2.1.0
4
+ Summary: Sol Programming Language Interpreter
5
+ Requires-Python: >=3.7
6
+ License-File: LICENSE
7
+ Dynamic: license-file
@@ -1,7 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
- interpreter/sol.py
5
4
  solpl.egg-info/PKG-INFO
6
5
  solpl.egg-info/SOURCES.txt
7
6
  solpl.egg-info/dependency_links.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ solpl = sol:main
@@ -0,0 +1 @@
1
+ sol
solpl-2.0.0/PKG-INFO DELETED
@@ -1,59 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: solpl
3
- Version: 2.0.0
4
- Summary: A lightweight, multi-threaded interpreter for the Sol programming language.
5
- Author-email: Your Name <your.email@example.com>
6
- License: Apache-2.0
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: Apache Software License
9
- Classifier: Operating System :: OS Independent
10
- Requires-Python: >=3.7
11
- Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
- Dynamic: license-file
14
-
15
- # Sol
16
- Sol is an interpreted language built with Python, originally designed to handle async operations only, but has expanded to a full scripting language.
17
-
18
- # Why did I build Sol?
19
-
20
- I needed something fast, that handled async natively, and which had very few keywords. Then came my first prototype, which only supported async functions. Sol now supports everything a programming language should need: Functions, variables, I/O, etc.
21
-
22
- # How to install Sol?
23
-
24
- ```bash
25
- pip install solpl
26
- ```
27
-
28
- # How to run a Sol script?
29
-
30
- ```bash
31
- solpl FILENAME.sol
32
- ```
33
-
34
- # Example:
35
-
36
- This demonstrates Sol's capabilities with async:
37
-
38
- ```lua
39
- countDown(taskName, maxCount)
40
- for i -> 1 to maxCount
41
- _out -> taskName
42
- end
43
- end
44
-
45
- main()
46
- _out -> 111
47
- countDown(777, 4) >> _async
48
- countDown(999, 4) >> _async
49
- _out -> 222
50
- end
51
- ```
52
-
53
- # License
54
-
55
- This repository is licensed with Apache License 2.0, see the LICENSE file for more details
56
-
57
- # Link to PyPi package:
58
-
59
- https://pypi.org/project/solpl/
@@ -1,445 +0,0 @@
1
- import math
2
- import threading
3
- import time
4
- import sys
5
- import os
6
- import urllib.request # Native network calls, zero external dependencies!
7
- import http.server
8
-
9
- class ReturnSignal(Exception):
10
- def __init__(self, value):
11
- self.value = value
12
-
13
- class SolInterpreter:
14
- def __init__(self):
15
- self.variables = {}
16
- self.thread_local = threading.local()
17
- self.functions = {}
18
- self.struct_blueprints = {}
19
- self.lines = []
20
- self.threads = []
21
-
22
- @property
23
- def scope_stack(self):
24
- if not hasattr(self.thread_local, "stack"):
25
- self.thread_local.stack = [self.variables]
26
- return self.thread_local.stack
27
-
28
- def _compute(self, expr):
29
- expr = str(expr).strip()
30
- ops = ['+', '-', '*', ':']
31
- for op in ops:
32
- if op in expr:
33
- left, right = expr.split(op)
34
- val1 = float(self._resolve(left))
35
- val2 = float(self._resolve(right))
36
- if op == '+': return val1 + val2
37
- if op == '-': return val1 - val2
38
- if op == '*': return val1 * val2
39
- if op == ':': return val1 / val2
40
- return self._resolve(expr)
41
-
42
- def _lookup(self, name):
43
- for scope in reversed(self.scope_stack):
44
- if name in scope:
45
- return scope[name]
46
- return None
47
-
48
- def _assign(self, name, val):
49
- self.scope_stack[-1][name] = val
50
-
51
- def _resolve(self, val):
52
- val = str(val).strip()
53
-
54
- # Handle built-in native functions
55
- if val.startswith("_fetch(") and val.endswith(")"):
56
- url_expr = val[7:-1].strip()
57
- url = str(self._compute(url_expr))
58
- return self._native_fetch(url)
59
-
60
- if "(" in val and val.endswith(")") and not val.startswith("_"):
61
- parts = val.split("(", 1)
62
- name = parts[0].strip()
63
- if name in self.functions:
64
- args_str = parts[1][:-1].strip()
65
- args = [self._compute(a.strip()) for a in args_str.split(",")] if args_str else []
66
- return self._call_function(name, args)
67
-
68
- if "[" in val and "]" in val:
69
- try:
70
- name, idx_part = val.split("[")
71
- idx = int(idx_part.replace("]", "").strip())
72
- container = self._lookup(name)
73
- if isinstance(container, list):
74
- return container[idx]
75
- except (ValueError, IndexError, KeyError): pass
76
- if "." in val:
77
- obj_name, prop = val.split(".")
78
- obj = self._lookup(obj_name)
79
- if isinstance(obj, dict):
80
- return obj.get(prop, 0)
81
-
82
- existing_val = self._lookup(val)
83
- if Carlsbad_val := self._lookup(val): return Carlsbad_val
84
- if existing_val is not None: return existing_val
85
- try: return float(val) if '.' in val else int(val)
86
- except: return val.replace('"', '').replace("'", "")
87
-
88
- def _async_worker(self, expr, action):
89
- result = self._compute(expr)
90
- if action == "_out":
91
- print(f"[ASYNC OUTPUT] {result}")
92
-
93
- def _async_input_worker(self, prompt, var_name):
94
- user_val = input(prompt)
95
- try:
96
- if '.' in user_val: user_val = float(user_val)
97
- else: user_val = int(user_val)
98
- except ValueError: pass
99
- self._assign(var_name, user_val)
100
-
101
- def _native_fetch(self, url):
102
- try:
103
- with urllib.request.urlopen(url, timeout=5) as response:
104
- return response.read().decode('utf-8')
105
- except Exception as e:
106
- return f"Error fetching URL: {str(e)}"
107
-
108
- def _native_listen(self, port, handler_name):
109
- interpreter_instance = self
110
- class SolHTTPHandler(http.server.BaseHTTPRequestHandler):
111
- def do_GET(self):
112
- self.send_response(200)
113
- self.send_header("Content-type", "text/html")
114
- self.end_headers()
115
- response_body = interpreter_instance._call_function(handler_name, [self.path])
116
- self.wfile.write(bytes(str(response_body), "utf-8"))
117
- def log_message(self, format, *args):
118
- pass
119
-
120
- def server_thread():
121
- server = http.server.HTTPServer(("0.0.0.0", int(port)), SolHTTPHandler)
122
- server.serve_forever()
123
-
124
- t = threading.Thread(target=server_thread, daemon=True)
125
- t.start()
126
- self.threads.append(t)
127
-
128
- def _evaluate_condition(self, cond):
129
- if "=" in cond:
130
- left, right = cond.split("=")
131
- return self._compute(left.strip()) == self._compute(right.strip())
132
- elif "<" in cond:
133
- left, right = cond.split("<")
134
- return self._compute(left.strip()) < self._compute(right.strip())
135
- elif ">" in cond:
136
- left, right = cond.split(">")
137
- return self._compute(left.strip()) > self._compute(right.strip())
138
- return False
139
-
140
- def _get_block_end(self, start_pc):
141
- depth = 1
142
- pc = start_pc + 1
143
- while pc < len(self.lines):
144
- line = self.lines[pc]
145
- if line.startswith("if ") or line.startswith("while ") or line.startswith("for "):
146
- depth += 1
147
- elif line == "end":
148
- depth -= 1
149
- if depth == 0:
150
- return pc
151
- pc += 1
152
- return pc
153
-
154
- def execute(self, code):
155
- self.lines = []
156
- for raw_line in code.split('\n'):
157
- if ';' in raw_line:
158
- raw_line = raw_line.split(';', 1)[0]
159
- trimmed = raw_line.strip()
160
- if trimmed:
161
- self.lines.append(trimmed)
162
-
163
- self.threads = []
164
-
165
- pc = 0
166
- while pc < len(self.lines):
167
- line = self.lines[pc]
168
- if "(" in line and ")" in line and "main" not in line and "end" not in line and "->" not in line and ">>" not in line and "?" not in line and not line.startswith("if ") and not line.startswith("while ") and not line.startswith("for "):
169
- parts = line.split("(")
170
- name = parts[0].strip()
171
- params_str = parts[1].replace(")", "").strip()
172
- params = [p.strip() for p in params_str.split(",")] if params_str else []
173
- self.functions[name] = {"start_pc": pc + 1, "params": params}
174
- elif "{" in line:
175
- pc = self._parse_struct(pc)
176
- continue
177
- pc += 1
178
-
179
- for i, line in enumerate(self.lines):
180
- if line == "main()":
181
- try:
182
- self._run_block(i + 1)
183
- except ReturnSignal:
184
- pass
185
- break
186
-
187
- for t in self.threads:
188
- if t.is_alive() and not t.daemon:
189
- t.join()
190
-
191
- def _parse_struct(self, pc):
192
- line = self.lines[pc]
193
- struct_name = line.split("{}")[0].strip()
194
- fields = {}
195
- pc += 1
196
- while pc < len(self.lines) and self.lines[pc] != "end":
197
- if "->" in self.lines[pc]:
198
- key, val = [x.strip() for x in self.lines[pc].split("->")]
199
- fields[key] = self._resolve(val)
200
- pc += 1
201
- self.struct_blueprints[struct_name] = fields
202
- self._assign(struct_name, fields.copy())
203
- return pc
204
-
205
- def _call_function(self, name, args):
206
- func_info = self.functions[name]
207
- start_pc = func_info["start_pc"]
208
- params = func_info["params"]
209
-
210
- local_scope = {}
211
- for param, arg in zip(params, args):
212
- local_scope[param] = arg
213
-
214
- self.scope_stack.append(local_scope)
215
-
216
- return_value = 0
217
- try:
218
- self._run_block(start_pc)
219
- except ReturnSignal as sig:
220
- return_value = sig.value
221
- finally:
222
- self.scope_stack.pop()
223
-
224
- return return_value
225
-
226
- def _execute_line(self, line):
227
- # Pipeline Check for Asynchronous Custom Prompts: "Name: " >> _input >> a
228
- if ">>" in line and "_input" in line:
229
- parts = [p.strip() for p in line.split(">>")]
230
- if len(parts) == 3 and parts[1] == "_input":
231
- prompt_string = str(self._compute(parts[0]))
232
- target_variable = parts[2]
233
-
234
- t = threading.Thread(target=self._async_input_worker, args=(prompt_string, target_variable))
235
- t.start()
236
- self.threads.append(t)
237
- return
238
-
239
- is_async_func = False
240
- if ">>" in line and "_async" in line and "(" in line and not line.startswith("_"):
241
- is_async_func = True
242
- line = line.split(">>")[0].strip()
243
-
244
- if line.startswith("_return ->"):
245
- val_expr = line.split("->", 1)[1].strip()
246
- result = self._compute(val_expr)
247
- raise ReturnSignal(result)
248
-
249
- elif ">>" in line and "_async" in line and not is_async_func:
250
- parts = line.split(">>")
251
- t = threading.Thread(target=self._async_worker, args=(parts[0].strip(), parts[2].strip()))
252
- t.start()
253
- self.threads.append(t)
254
-
255
- elif line.startswith("_in ->"):
256
- var_name = line.split("->")[1].strip()
257
- user_val = input(f"[INPUT REQUIRED FOR %s]: " % var_name)
258
- try:
259
- if '.' in user_val: user_val = float(user_val)
260
- else: user_val = int(user_val)
261
- except ValueError: pass
262
- self._assign(var_name, user_val)
263
-
264
- elif "_add(" in line:
265
- content = line.replace("_add(", "").replace(")", "")
266
- parts = [p.strip() for p in content.split(",")]
267
- container = self._lookup(parts[0])
268
- if isinstance(container, list):
269
- container.insert(int(parts[1]), self._resolve(parts[2]))
270
- elif "_remove(" in line:
271
- content = line.replace("_remove(", "").replace(")", "")
272
- parts = [p.strip() for p in content.split(",")]
273
- container = self._lookup(parts[0])
274
- if isinstance(container, list):
275
- container.pop(int(parts[1]))
276
- elif "_listen(" in line:
277
- content = line.replace("_listen(", "").replace(")", "")
278
- port_expr, handler_expr = [p.strip() for p in content.split(",")]
279
- port = self._compute(port_expr)
280
- self._native_listen(port, handler_expr)
281
- elif "_out" in line:
282
- val = line.split("->")[1].strip()
283
- print(self._compute(val))
284
-
285
- elif "mylist<" in line and ">" in line:
286
- var_name = line.split("<")[1].split(">")[0]
287
- self._assign(var_name, [])
288
-
289
- elif "->" in line:
290
- var, val = [x.strip() for x in line.split("->")]
291
- if "." in var:
292
- obj, prop = var.split(".")
293
- target_obj = self._lookup(obj)
294
- if isinstance(target_obj, dict):
295
- target_obj[prop] = self._compute(val)
296
- else:
297
- self._assign(var, self._compute(val))
298
- else:
299
- if "(" in line and line.endswith(")") and not line.startswith("_"):
300
- parts = line.split("(")
301
- name = parts[0].strip()
302
- if name in self.functions:
303
- args_str = parts[1][:-1].strip()
304
- args = [self._compute(a.strip()) for a in args_str.split(",")] if args_str else []
305
-
306
- if is_async_func:
307
- t = threading.Thread(target=self._call_function, args=(name, args))
308
- t.start()
309
- self.threads.append(t)
310
- else:
311
- self._call_function(name, args)
312
-
313
- def _run_block(self, start_pc):
314
- pc = start_pc
315
- control_stack = []
316
-
317
- while pc < len(self.lines):
318
- line = self.lines[pc]
319
- is_executing = all(level["executing"] for level in control_stack)
320
-
321
- if line.startswith("if "):
322
- cond = line.split("if ", 1)[1].strip()
323
- if is_executing:
324
- cond_true = self._evaluate_condition(cond)
325
- control_stack.append({"type": "if", "executing": cond_true, "any_branch_true": cond_true})
326
- else:
327
- control_stack.append({"type": "if", "executing": False, "any_branch_true": True})
328
- pc += 1
329
- continue
330
-
331
- elif line.startswith("elseif "):
332
- cond = line.split("elseif ", 1)[1].strip()
333
- parent_active = all(level["executing"] for level in control_stack[:-1]) if len(control_stack) > 1 else True
334
-
335
- if control_stack and control_stack[-1]["type"] == "if":
336
- if parent_active and not control_stack[-1]["any_branch_true"]:
337
- cond_true = self._evaluate_condition(cond)
338
- control_stack[-1]["executing"] = cond_true
339
- control_stack[-1]["any_branch_true"] = cond_true
340
- else:
341
- control_stack[-1]["executing"] = False
342
- pc += 1
343
- continue
344
-
345
- elif line == "else":
346
- parent_active = all(level["executing"] for level in control_stack[:-1]) if len(control_stack) > 1 else True
347
- if control_stack and control_stack[-1]["type"] == "if":
348
- if parent_active and not control_stack[-1]["any_branch_true"]:
349
- control_stack[-1]["executing"] = True
350
- control_stack[-1]["any_branch_true"] = True
351
- else:
352
- control_stack[-1]["executing"] = False
353
- pc += 1
354
- continue
355
-
356
- elif line.startswith("while "):
357
- cond = line.split("while ", 1)[1].strip()
358
- if is_executing:
359
- end_pc = self._get_block_end(pc)
360
- if self._evaluate_condition(cond):
361
- control_stack.append({"type": "while", "executing": True, "start_pc": pc, "end_pc": end_pc})
362
- pc += 1
363
- else:
364
- pc = end_pc + 1
365
- else:
366
- control_stack.append({"type": "while", "executing": False})
367
- pc += 1
368
- continue
369
-
370
- elif line.startswith("for "):
371
- if is_executing:
372
- parts = line.split("for ", 1)[1].split("->")
373
- var_name = parts[0].strip()
374
- range_parts = parts[1].split(" to ")
375
- start_val = int(self._compute(range_parts[0].strip()))
376
- end_val = int(self._compute(range_parts[1].strip()))
377
-
378
- self._assign(var_name, start_val)
379
- end_pc = self._get_block_end(pc)
380
-
381
- if start_val <= end_val:
382
- control_stack.append({"type": "for", "executing": True, "var": var_name, "end_val": end_val, "start_pc": pc, "end_pc": end_pc})
383
- pc += 1
384
- else:
385
- pc = end_pc + 1
386
- else:
387
- control_stack.append({"type": "for", "executing": False})
388
- pc += 1
389
- continue
390
-
391
- elif line == "end":
392
- if control_stack:
393
- top = control_stack[-1]
394
- if top.get("type") == "while" and top["executing"]:
395
- pc = top["start_pc"]
396
- control_stack.pop()
397
- continue
398
- elif top.get("type") == "for" and top["executing"]:
399
- var_name = top["var"]
400
- next_val = self._lookup(var_name) + 1
401
- if next_val <= top["end_val"]:
402
- self._assign(var_name, next_val)
403
- pc = top["start_pc"] + 1
404
- continue
405
- else:
406
- control_stack.pop()
407
- pc += 1
408
- continue
409
- else:
410
- control_stack.pop()
411
- pc += 1
412
- continue
413
- else:
414
- break
415
-
416
- if is_executing:
417
- if "?" in line:
418
- cond, action = line.split("?", 1)
419
- if self._evaluate_condition(cond.strip()):
420
- self._execute_line(action.strip())
421
- else:
422
- self._execute_line(line)
423
- pc += 1
424
-
425
- def main():
426
- if len(sys.argv) < 2:
427
- print("Error: No script file provided.\nUsage: solpl <filename.sol>", file=sys.stderr)
428
- sys.exit(1)
429
-
430
- filename = sys.argv[1]
431
- if not filename.endswith(".sol"):
432
- print("Error: File must have a '.sol' extension.", file=sys.stderr)
433
- sys.exit(1)
434
- if not os.path.exists(filename):
435
- print(f"Error: File '{filename}' not found.", file=sys.stderr)
436
- sys.exit(1)
437
-
438
- with open(filename, "r") as f:
439
- code_content = f.read()
440
-
441
- engine = SolInterpreter()
442
- engine.execute(code_content)
443
-
444
- if __name__ == "__main__":
445
- main()
@@ -1,22 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "solpl"
7
- version = "2.0.0"
8
- authors = [
9
- { name="Your Name", email="your.email@example.com" }
10
- ]
11
- description = "A lightweight, multi-threaded interpreter for the Sol programming language."
12
- readme = "README.md"
13
- license = {text = "Apache-2.0"}
14
- requires-python = ">=3.7"
15
- classifiers = [
16
- "Programming Language :: Python :: 3",
17
- "License :: OSI Approved :: Apache Software License",
18
- "Operating System :: OS Independent",
19
- ]
20
-
21
- [project.scripts]
22
- solpl = "interpreter.sol:main"
@@ -1,59 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: solpl
3
- Version: 2.0.0
4
- Summary: A lightweight, multi-threaded interpreter for the Sol programming language.
5
- Author-email: Your Name <your.email@example.com>
6
- License: Apache-2.0
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: License :: OSI Approved :: Apache Software License
9
- Classifier: Operating System :: OS Independent
10
- Requires-Python: >=3.7
11
- Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
- Dynamic: license-file
14
-
15
- # Sol
16
- Sol is an interpreted language built with Python, originally designed to handle async operations only, but has expanded to a full scripting language.
17
-
18
- # Why did I build Sol?
19
-
20
- I needed something fast, that handled async natively, and which had very few keywords. Then came my first prototype, which only supported async functions. Sol now supports everything a programming language should need: Functions, variables, I/O, etc.
21
-
22
- # How to install Sol?
23
-
24
- ```bash
25
- pip install solpl
26
- ```
27
-
28
- # How to run a Sol script?
29
-
30
- ```bash
31
- solpl FILENAME.sol
32
- ```
33
-
34
- # Example:
35
-
36
- This demonstrates Sol's capabilities with async:
37
-
38
- ```lua
39
- countDown(taskName, maxCount)
40
- for i -> 1 to maxCount
41
- _out -> taskName
42
- end
43
- end
44
-
45
- main()
46
- _out -> 111
47
- countDown(777, 4) >> _async
48
- countDown(999, 4) >> _async
49
- _out -> 222
50
- end
51
- ```
52
-
53
- # License
54
-
55
- This repository is licensed with Apache License 2.0, see the LICENSE file for more details
56
-
57
- # Link to PyPi package:
58
-
59
- https://pypi.org/project/solpl/
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- solpl = interpreter.sol:main
@@ -1 +0,0 @@
1
- interpreter
File without changes
File without changes
File without changes