easypy-lang 2.0.1__tar.gz → 2.0.2__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.
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/PKG-INFO +1 -1
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/modules_real.py +9 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/transpiler.py +106 -13
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/PKG-INFO +1 -1
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/setup.py +1 -1
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/README.md +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/__init__.py +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/cli.py +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/engine.py +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/epi.py +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang/modules.py +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/SOURCES.txt +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/dependency_links.txt +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/entry_points.txt +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/requires.txt +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/easypy_lang.egg-info/top_level.txt +0 -0
- {easypy_lang-2.0.1 → easypy_lang-2.0.2}/setup.cfg +0 -0
|
@@ -9,6 +9,15 @@ import time
|
|
|
9
9
|
import json
|
|
10
10
|
import threading
|
|
11
11
|
|
|
12
|
+
# Global Aliases for Easypy -> Python compatibility
|
|
13
|
+
true = True
|
|
14
|
+
false = False
|
|
15
|
+
null = None
|
|
16
|
+
|
|
17
|
+
# Built-in String Helpers
|
|
18
|
+
def upper(s): return str(s).upper()
|
|
19
|
+
def lower(s): return str(s).lower()
|
|
20
|
+
|
|
12
21
|
# ==================== GUI (Tkinter) ====================
|
|
13
22
|
class _GUIImpl:
|
|
14
23
|
def __init__(self):
|
|
@@ -155,17 +155,82 @@ class EasypyTranspiler:
|
|
|
155
155
|
|
|
156
156
|
return "".join(normalized)
|
|
157
157
|
|
|
158
|
+
def _clean_expression(self, text):
|
|
159
|
+
"""Helper to convert C-style syntax to Python"""
|
|
160
|
+
# Operators
|
|
161
|
+
text = text.replace("===", "==")
|
|
162
|
+
text = text.replace("&&", " and ")
|
|
163
|
+
text = text.replace("||", " or ")
|
|
164
|
+
|
|
165
|
+
# '!' but not '!='
|
|
166
|
+
# Only replace if preceded by start-of-line, space, '(', '[', or '='
|
|
167
|
+
# This prevents replacing '!' inside strings like "Hello!"
|
|
168
|
+
text = re.sub(r'(?:^|(?<=[=\s(\[]))!(?!=)', 'not ', text)
|
|
169
|
+
|
|
170
|
+
# 'true'/'false'/'null' are handled by modules_real.py aliases at runtime,
|
|
171
|
+
# but replacing them here can be safer for some edge cases.
|
|
172
|
+
# But let's stick to the aliases to avoid accidental string replacement.
|
|
173
|
+
|
|
174
|
+
return text
|
|
175
|
+
|
|
176
|
+
def _preprocess_line(self, line):
|
|
177
|
+
"""Handle 'Advanced' syntax: --->, if =, implicit f-strings"""
|
|
178
|
+
|
|
179
|
+
# 1. implicit f-strings for print/log
|
|
180
|
+
# Detect if {var} pattern exists inside quotes
|
|
181
|
+
if ('print(' in line or 'log ' in line) and '{' in line and '}' in line:
|
|
182
|
+
# Simple heuristic: inject 'f' before quotes
|
|
183
|
+
# Handle double quotes
|
|
184
|
+
line = re.sub(r'print\(\s*"', 'print(f"', line)
|
|
185
|
+
line = re.sub(r'log\s+"', 'log f"', line)
|
|
186
|
+
# Handle single quotes
|
|
187
|
+
line = re.sub(r"print\(\s*'", "print(f'", line)
|
|
188
|
+
line = re.sub(r"log\s+'", "log f'", line)
|
|
189
|
+
|
|
190
|
+
# 2. Syntax Sugar: Arrow
|
|
191
|
+
if "--->" in line:
|
|
192
|
+
line = line.replace("--->", ":")
|
|
193
|
+
|
|
194
|
+
# 3. Syntax Sugar: if =, else if =, else =
|
|
195
|
+
line = re.sub(r'^(\s*)if\s*=\s*', r'\1if ', line)
|
|
196
|
+
line = re.sub(r'^(\s*)else\s*if\s*=\s*', r'\1elif ', line)
|
|
197
|
+
# Fix: else = statement needs a colon for inline usage
|
|
198
|
+
line = re.sub(r'^(\s*)else\s*=\s*', r'\1else: ', line)
|
|
199
|
+
|
|
200
|
+
# 4. Handle "else if" without equals
|
|
201
|
+
line = line.replace("else if", "elif")
|
|
202
|
+
|
|
203
|
+
# 5. Loop syntax conversion (loop N times)
|
|
204
|
+
# Supports both "loop 3 times:" and "loop 3 times {"
|
|
205
|
+
# We replace the start with pythonic loop
|
|
206
|
+
loop_match = re.match(r'^(\s*)loop\s+(\d+)\s+times', line)
|
|
207
|
+
if loop_match:
|
|
208
|
+
indent = loop_match.group(1)
|
|
209
|
+
count = loop_match.group(2)
|
|
210
|
+
# Replace 'loop N times' with 'for _ in range(N)'
|
|
211
|
+
# We leave the suffix (colon or brace) for the next step
|
|
212
|
+
line = re.sub(r'loop\s+\d+\s+times', f'for _ in range({count})', line, count=1)
|
|
213
|
+
|
|
214
|
+
return line
|
|
215
|
+
|
|
158
216
|
def _process_line(self, raw_line):
|
|
159
217
|
# Indentation handling (Closing Brace)
|
|
160
218
|
# Handle cases like "}" or "} else {" or "}}"
|
|
219
|
+
closing_braces = ""
|
|
161
220
|
while raw_line.startswith("}"):
|
|
221
|
+
ctx = self.context_stack[-1] if self.context_stack else 'block'
|
|
222
|
+
if ctx == 'dict':
|
|
223
|
+
closing_braces += "}"
|
|
224
|
+
|
|
162
225
|
self.indent_level -= 1
|
|
163
226
|
if self.indent_level < 0: self.indent_level = 0
|
|
164
227
|
if self.context_stack: self.context_stack.pop()
|
|
165
228
|
raw_line = raw_line[1:].strip()
|
|
166
229
|
|
|
167
|
-
# If line was just "}", it is now empty.
|
|
230
|
+
# If line was just "}", it is now empty.
|
|
168
231
|
if not raw_line:
|
|
232
|
+
if closing_braces:
|
|
233
|
+
return f"{' ' * self.indent_level}{closing_braces}"
|
|
169
234
|
return None
|
|
170
235
|
|
|
171
236
|
# Prepare current indentation string
|
|
@@ -175,6 +240,13 @@ class EasypyTranspiler:
|
|
|
175
240
|
if raw_line.startswith('#') or raw_line.startswith('//'):
|
|
176
241
|
return f"{indent}#{raw_line}"
|
|
177
242
|
|
|
243
|
+
# === PREPROCESSOR ===
|
|
244
|
+
# Handle "Advanced" syntax (Arrow, if=, etc)
|
|
245
|
+
raw_line = self._preprocess_line(raw_line)
|
|
246
|
+
|
|
247
|
+
# Apply basic expression cleanup (&& -> and)
|
|
248
|
+
raw_line = self._clean_expression(raw_line)
|
|
249
|
+
|
|
178
250
|
# === TRANSLATION RULES ===
|
|
179
251
|
|
|
180
252
|
# 1. Imports
|
|
@@ -249,12 +321,14 @@ class EasypyTranspiler:
|
|
|
249
321
|
condition = raw_line[2:-1].strip()
|
|
250
322
|
# Handle if(x) vs if x
|
|
251
323
|
if condition.startswith("(") and condition.endswith(")"): condition = condition
|
|
324
|
+
condition = self._clean_expression(condition)
|
|
252
325
|
self.indent_level += 1
|
|
253
326
|
self.context_stack.append('block')
|
|
254
327
|
return f"{indent}if {condition}:"
|
|
255
328
|
|
|
256
329
|
if raw_line.startswith("elif") and raw_line.endswith("{"):
|
|
257
330
|
condition = raw_line[4:-1].strip()
|
|
331
|
+
condition = self._clean_expression(condition)
|
|
258
332
|
self.indent_level += 1
|
|
259
333
|
self.context_stack.append('block')
|
|
260
334
|
return f"{indent}elif {condition}:"
|
|
@@ -265,31 +339,50 @@ class EasypyTranspiler:
|
|
|
265
339
|
return f"{indent}else:"
|
|
266
340
|
|
|
267
341
|
# 6. Loops
|
|
268
|
-
|
|
269
|
-
if
|
|
270
|
-
count = loop_match.group(1)
|
|
342
|
+
# (Handled by preprocessor now, but we keep this for block context tracking if needed)
|
|
343
|
+
if raw_line.startswith("for ") and " range(" in raw_line and (raw_line.endswith("{") or raw_line.endswith(":")):
|
|
271
344
|
self.indent_level += 1
|
|
272
345
|
self.context_stack.append('block')
|
|
273
|
-
|
|
346
|
+
# If it ends with {, strip it for python
|
|
347
|
+
if raw_line.endswith("{"):
|
|
348
|
+
return f"{indent}{raw_line[:-1].strip()}:"
|
|
349
|
+
return f"{indent}{raw_line}"
|
|
274
350
|
|
|
275
|
-
if raw_line.startswith("while") and raw_line.endswith("{"):
|
|
276
|
-
|
|
351
|
+
if raw_line.startswith("while") and (raw_line.endswith("{") or raw_line.endswith(":")):
|
|
352
|
+
clean_line = raw_line[:-1].strip() if raw_line.endswith("{") else raw_line[:-1].strip()
|
|
277
353
|
self.indent_level += 1
|
|
278
354
|
self.context_stack.append('block')
|
|
279
|
-
return f"{indent}
|
|
355
|
+
return f"{indent}{clean_line}:"
|
|
280
356
|
|
|
281
|
-
if raw_line.startswith("for ") and raw_line.endswith("{"):
|
|
282
|
-
|
|
357
|
+
if raw_line.startswith("for ") and (raw_line.endswith("{") or raw_line.endswith(":")):
|
|
358
|
+
clean_line = raw_line[:-1].strip() if raw_line.endswith("{") else raw_line[:-1].strip()
|
|
283
359
|
self.indent_level += 1
|
|
284
360
|
self.context_stack.append('block')
|
|
285
|
-
return f"{indent}
|
|
361
|
+
return f"{indent}{clean_line}:"
|
|
286
362
|
|
|
287
363
|
# 7. Generic Block
|
|
288
364
|
if raw_line.endswith("{"):
|
|
289
365
|
clean_line = raw_line[:-1].strip()
|
|
366
|
+
clean_line = self._clean_expression(clean_line)
|
|
367
|
+
|
|
368
|
+
# CRITICAL FIX: Detect Dictionary vs Code Block
|
|
369
|
+
# If it is an assignment (x = {), keep the brace, do strict Python dict open.
|
|
370
|
+
# Regex checks for "var =" or "word =" pattern at end of line
|
|
371
|
+
# But NOT "if x == {" (comparison)
|
|
372
|
+
# Simple heuristic: If it has "=" and not " if " or " while ", it's likely data.
|
|
373
|
+
is_assignment = re.search(r'[^=!<>]=[^=]', clean_line) or clean_line.endswith("=")
|
|
374
|
+
|
|
290
375
|
self.indent_level += 1
|
|
291
|
-
|
|
292
|
-
|
|
376
|
+
if is_assignment:
|
|
377
|
+
# It's a dict! Keep the brace.
|
|
378
|
+
self.context_stack.append('dict')
|
|
379
|
+
return f"{indent}{clean_line} {{"
|
|
380
|
+
else:
|
|
381
|
+
# It's a code block! Use colon.
|
|
382
|
+
self.context_stack.append('block')
|
|
383
|
+
return f"{indent}{clean_line}:"
|
|
293
384
|
|
|
294
385
|
# 8. Standard Line
|
|
386
|
+
# Apply cleanup to standard lines too (assignments, expressions)
|
|
387
|
+
# raw_line = self._clean_expression(raw_line) # Already done in preprocess
|
|
295
388
|
return f"{indent}{raw_line}"
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="easypy-lang",
|
|
8
|
-
version="2.0.
|
|
8
|
+
version="2.0.2",
|
|
9
9
|
author="Vadik Goel",
|
|
10
10
|
author_email="vadikgoel1@gmail.com",
|
|
11
11
|
description="A simple, powerful language for AI, ML, and apps - No coding experience needed!",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|