easycoder 241231.1__py2.py3-none-any.whl → 250103.1__py2.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.

Potentially problematic release.


This version of easycoder might be problematic. Click here for more details.

easycoder/__init__.py CHANGED
@@ -10,4 +10,4 @@ from .ec_program import *
10
10
  from .ec_timestamp import *
11
11
  from .ec_value import *
12
12
 
13
- __version__ = "241231.1"
13
+ __version__ = "250103.1"
easycoder/ec_core.py CHANGED
@@ -1,4 +1,4 @@
1
- import json, math, hashlib, threading, os, subprocess, sys, requests, time, numbers
1
+ import json, math, hashlib, threading, os, subprocess, sys, requests, time, numbers, base64
2
2
  from psutil import Process
3
3
  from datetime import datetime, timezone
4
4
  from random import randrange
@@ -10,6 +10,7 @@ class Core(Handler):
10
10
 
11
11
  def __init__(self, compiler):
12
12
  Handler.__init__(self, compiler)
13
+ self.encoding = 'utf-8'
13
14
 
14
15
  def getName(self):
15
16
  return 'core'
@@ -464,23 +465,6 @@ class Core(Handler):
464
465
  self.program.putSymbolValue(target, retval);
465
466
  return self.nextPC()
466
467
 
467
- # Call a subroutine
468
- def k_gosub(self, command):
469
- if self.peek() == 'to':
470
- self.nextToken()
471
- command['gosub'] = self.nextToken()
472
- self.add(command)
473
- return True
474
-
475
- def r_gosub(self, command):
476
- label = command['gosub'] + ':'
477
- address = self.symbols[label]
478
- if address != None:
479
- self.stack.append(self.nextPC())
480
- return address
481
- RuntimeError(self.program, f'There is no label "{label + ":"}"')
482
- return None
483
-
484
468
  # Go to a label
485
469
  def k_go(self, command):
486
470
  if self.peek() == 'to':
@@ -506,6 +490,23 @@ class Core(Handler):
506
490
  def r_gotoPC(self, command):
507
491
  return command['goto']
508
492
 
493
+ # Call a subroutine
494
+ def k_gosub(self, command):
495
+ if self.peek() == 'to':
496
+ self.nextToken()
497
+ command['gosub'] = self.nextToken()
498
+ self.add(command)
499
+ return True
500
+
501
+ def r_gosub(self, command):
502
+ label = command['gosub'] + ':'
503
+ address = self.symbols[label]
504
+ if address != None:
505
+ self.stack.append(self.nextPC())
506
+ return address
507
+ RuntimeError(self.program, f'There is no label "{label + ":"}"')
508
+ return None
509
+
509
510
  # if <condition> <action> [else <action>]
510
511
  def k_if(self, command):
511
512
  command['condition'] = self.nextCondition()
@@ -1032,25 +1033,32 @@ class Core(Handler):
1032
1033
  command['target'] = target['name']
1033
1034
  self.add(command)
1034
1035
  return True
1036
+ return False
1035
1037
 
1036
1038
  token = self.getToken()
1037
1039
  if token == 'the':
1038
1040
  token = self.nextToken()
1041
+ command['type'] = token
1042
+
1039
1043
  if token == 'elements':
1040
1044
  self.nextToken()
1041
1045
  if self.peek() == 'of':
1042
1046
  self.nextToken()
1043
1047
  if self.nextIsSymbol():
1044
- command['type'] = 'elements'
1045
1048
  command['name'] = self.getToken()
1046
1049
  if self.peek() == 'to':
1047
1050
  self.nextToken()
1048
1051
  command['elements'] = self.nextValue()
1049
1052
  self.add(command)
1050
1053
  return True
1054
+
1055
+ elif token == 'encoding':
1056
+ if self.nextIs('to'):
1057
+ command['encoding'] = self.nextValue()
1058
+ self.add(command)
1059
+ return True
1051
1060
 
1052
- if token == 'property':
1053
- command['type'] = 'property'
1061
+ elif token == 'property':
1054
1062
  command['name'] = self.nextValue()
1055
1063
  if self.nextIs('of'):
1056
1064
  if self.nextIsSymbol():
@@ -1060,8 +1068,7 @@ class Core(Handler):
1060
1068
  self.add(command)
1061
1069
  return True
1062
1070
 
1063
- if token == 'element':
1064
- command['type'] = 'element'
1071
+ elif token == 'element':
1065
1072
  command['index'] = self.nextValue()
1066
1073
  if self.nextIs('of'):
1067
1074
  if self.nextIsSymbol():
@@ -1070,7 +1077,6 @@ class Core(Handler):
1070
1077
  command['value'] = self.nextValue()
1071
1078
  self.add(command)
1072
1079
  return True
1073
-
1074
1080
  return False
1075
1081
 
1076
1082
  def r_set(self, command):
@@ -1083,7 +1089,7 @@ class Core(Handler):
1083
1089
  self.putSymbolValue(target, val)
1084
1090
  return self.nextPC()
1085
1091
 
1086
- if cmdType == 'elements':
1092
+ elif cmdType == 'elements':
1087
1093
  symbolRecord = self.getVariable(command['name'])
1088
1094
  elements = self.getRuntimeValue(command['elements'])
1089
1095
  currentElements = symbolRecord['elements']
@@ -1102,7 +1108,7 @@ class Core(Handler):
1102
1108
  symbolRecord['value'] = newValue
1103
1109
  return self.nextPC()
1104
1110
 
1105
- if cmdType == 'element':
1111
+ elif cmdType == 'element':
1106
1112
  value = self.getRuntimeValue(command['value'])
1107
1113
  index = self.getRuntimeValue(command['index'])
1108
1114
  target = self.getVariable(command['target'])
@@ -1117,7 +1123,11 @@ class Core(Handler):
1117
1123
  self.putSymbolValue(target, val)
1118
1124
  return self.nextPC()
1119
1125
 
1120
- if cmdType == 'property':
1126
+ elif cmdType == 'encoding':
1127
+ self.encoding = self.getRuntimeValue(command['encoding'])
1128
+ return self.nextPC()
1129
+
1130
+ elif cmdType == 'property':
1121
1131
  value = self.getRuntimeValue(command['value'])
1122
1132
  name = self.getRuntimeValue(command['name'])
1123
1133
  target = command['target']
@@ -1469,10 +1479,10 @@ class Core(Handler):
1469
1479
  return value
1470
1480
  return None
1471
1481
 
1472
- if token in ['now', 'today', 'newline', 'break', 'empty']:
1482
+ if token in ['now', 'today', 'newline', 'tab', 'empty']:
1473
1483
  return value
1474
1484
 
1475
- if token in ['date', 'encode', 'decode', 'stringify', 'json', 'lowercase', 'uppercase', 'hash', 'random', 'float', 'integer']:
1485
+ if token in ['stringify', 'json', 'lowercase', 'uppercase', 'hash', 'random', 'float', 'integer', 'encode', 'decode']:
1476
1486
  value['content'] = self.nextValue()
1477
1487
  return value
1478
1488
 
@@ -1555,7 +1565,9 @@ class Core(Handler):
1555
1565
  if token == 'index':
1556
1566
  if self.nextIs('of'):
1557
1567
  if self.nextIsSymbol():
1568
+ value['variable'] = self.getSymbolRecord()['name']
1558
1569
  if self.peek() == 'in':
1570
+ value['value'] = None
1559
1571
  value['type'] = 'indexOf'
1560
1572
  if self.nextIsSymbol():
1561
1573
  value['target'] = self.getSymbolRecord()['name']
@@ -1564,8 +1576,9 @@ class Core(Handler):
1564
1576
  value['name'] = self.getToken()
1565
1577
  return value
1566
1578
  else:
1567
- value['value1'] = self.getValue()
1579
+ value['value'] = self.getValue()
1568
1580
  if self.nextIs('in'):
1581
+ value['variable'] = None
1569
1582
  value['type'] = 'indexOf'
1570
1583
  if self.nextIsSymbol():
1571
1584
  value['target'] = self.getSymbolRecord()['name']
@@ -1631,7 +1644,8 @@ class Core(Handler):
1631
1644
  return value
1632
1645
 
1633
1646
  if token == 'files':
1634
- if self.nextIs('of'):
1647
+ token = self.nextToken()
1648
+ if token in ['in', 'of']:
1635
1649
  value['target'] = self.nextValue()
1636
1650
  return value
1637
1651
  return None
@@ -1716,6 +1730,14 @@ class Core(Handler):
1716
1730
  value['content'] = round(math.cos(angle * 0.01745329) * radius)
1717
1731
  return value
1718
1732
 
1733
+ def v_count(self, v):
1734
+ variable = self.getVariable(v['name'])
1735
+ content = variable['value'][variable['index']]['content']
1736
+ value = {}
1737
+ value['type'] = 'int'
1738
+ value['content'] = len(content)
1739
+ return value
1740
+
1719
1741
  def v_datime(self, v):
1720
1742
  ts = self.getRuntimeValue(v['timestamp'])
1721
1743
  fmt = v['format']
@@ -1729,9 +1751,17 @@ class Core(Handler):
1729
1751
  return value
1730
1752
 
1731
1753
  def v_decode(self, v):
1754
+ content = self.getRuntimeValue(v['content'])
1732
1755
  value = {}
1733
1756
  value['type'] = 'text'
1734
- value['content'] = self.program.decode(v['content'])
1757
+ if self.encoding == 'utf-8':
1758
+ value['content'] = content.decode('utf-8')
1759
+ elif self.encoding == 'base64':
1760
+ base64_bytes = content.encode('ascii')
1761
+ message_bytes = base64.b64decode(base64_bytes)
1762
+ value['content'] = message_bytes.decode('ascii')
1763
+ else:
1764
+ value = v
1735
1765
  return value
1736
1766
 
1737
1767
  def v_element(self, v):
@@ -1754,18 +1784,9 @@ class Core(Handler):
1754
1784
  var = self.getVariable(v['name'])
1755
1785
  value = {}
1756
1786
  value['type'] = 'int'
1757
- # value['content'] = self.getVariable(v['name'])['elements']
1758
1787
  value['content'] = var['elements']
1759
1788
  return value
1760
1789
 
1761
- def v_count(self, v):
1762
- variable = self.getVariable(v['name'])
1763
- content = variable['value'][variable['index']]['content']
1764
- value = {}
1765
- value['type'] = 'int'
1766
- value['content'] = len(content)
1767
- return value
1768
-
1769
1790
  def v_empty(self, v):
1770
1791
  value = {}
1771
1792
  value['type'] = 'text'
@@ -1773,9 +1794,17 @@ class Core(Handler):
1773
1794
  return value
1774
1795
 
1775
1796
  def v_encode(self, v):
1797
+ content = self.getRuntimeValue(v['content'])
1776
1798
  value = {}
1777
1799
  value['type'] = 'text'
1778
- value['content'] = self.program.encode(v['content'])
1800
+ if self.encoding == 'utf-8':
1801
+ value['content'] = content.encode('utf-8')
1802
+ elif self.encoding == 'base64':
1803
+ data_bytes = content.encode('ascii')
1804
+ base64_bytes = base64.b64encode(data_bytes)
1805
+ value['content'] = base64_bytes.decode('ascii')
1806
+ else:
1807
+ value = v
1779
1808
  return value
1780
1809
 
1781
1810
  def v_error(self, v):
@@ -1789,21 +1818,22 @@ class Core(Handler):
1789
1818
  value['content'] = errorReason
1790
1819
  return value
1791
1820
 
1792
- def v_stringify(self, v):
1793
- item = self.getRuntimeValue(v['content'])
1821
+ def v_files(self, v):
1822
+ v = self.getRuntimeValue(v['target'])
1794
1823
  value = {}
1795
1824
  value['type'] = 'text'
1796
- value['content'] = json.dumps(item)
1825
+ value['content'] = os.listdir(v)
1797
1826
  return value
1798
1827
 
1799
- def v_json(self, v):
1800
- item = self.getRuntimeValue(v['content'])
1828
+ def v_float(self, v):
1829
+ val = self.getRuntimeValue(v['content'])
1801
1830
  value = {}
1802
- value['type'] = 'object'
1831
+ value['type'] = 'float'
1803
1832
  try:
1804
- value['content'] = json.loads(item)
1833
+ value['content'] = float(val)
1805
1834
  except:
1806
- RuntimeError(self.program, 'Cannot encode value')
1835
+ RuntimeWarning(self.program, f'Value cannot be parsed as floating-point')
1836
+ value['content'] = 0.0
1807
1837
  return value
1808
1838
 
1809
1839
  def v_from(self, v):
@@ -1827,17 +1857,6 @@ class Core(Handler):
1827
1857
  value['content'] = hashlib.sha256(hashval.encode('utf-8')).hexdigest()
1828
1858
  return value
1829
1859
 
1830
- def v_float(self, v):
1831
- val = self.getRuntimeValue(v['content'])
1832
- value = {}
1833
- value['type'] = 'float'
1834
- try:
1835
- value['content'] = float(val)
1836
- except:
1837
- RuntimeWarning(self.program, f'Value cannot be parsed as floating-point')
1838
- value['content'] = 0.0
1839
- return value
1840
-
1841
1860
  def v_index(self, v):
1842
1861
  value = {}
1843
1862
  value['type'] = 'int'
@@ -1845,16 +1864,22 @@ class Core(Handler):
1845
1864
  return value
1846
1865
 
1847
1866
  def v_indexOf(self, v):
1848
- value1 = v['value1']
1867
+ value = v['value']
1868
+ if value == None:
1869
+ value = self.getSymbolValue(v['variable'])['content']
1870
+ else:
1871
+ value = self.getRuntimeValue(value)
1849
1872
  target = self.getVariable(v['target'])
1850
- try:
1851
- index = target['value'].index(value1)
1852
- except:
1853
- index = -1
1854
- value = {}
1855
- value['type'] = 'int'
1856
- value['content'] = index
1857
- return value
1873
+ data = self.getSymbolValue(target)['content']
1874
+ index = -1
1875
+ for n in range(0, len(data)):
1876
+ if data[n] == value:
1877
+ index = n
1878
+ break
1879
+ retval = {}
1880
+ retval['type'] = 'int'
1881
+ retval['content'] = index
1882
+ return retval
1858
1883
 
1859
1884
  def v_integer(self, v):
1860
1885
  val = self.getRuntimeValue(v['content'])
@@ -1863,6 +1888,16 @@ class Core(Handler):
1863
1888
  value['content'] = int(val)
1864
1889
  return value
1865
1890
 
1891
+ def v_json(self, v):
1892
+ item = self.getRuntimeValue(v['content'])
1893
+ value = {}
1894
+ value['type'] = 'object'
1895
+ try:
1896
+ value['content'] = json.loads(item)
1897
+ except:
1898
+ RuntimeError(self.program, 'Cannot encode value')
1899
+ return value
1900
+
1866
1901
  def v_keys(self, v):
1867
1902
  value = {}
1868
1903
  value['type'] = 'int'
@@ -1893,18 +1928,20 @@ class Core(Handler):
1893
1928
  value['content'] = content.lower()
1894
1929
  return value
1895
1930
 
1896
- def v_uppercase(self, v):
1897
- content = self.getRuntimeValue(v['content'])
1931
+ def v_memory(self, v):
1932
+ process: Process = Process(os.getpid())
1933
+ megabytes: float = process.memory_info().rss / (1024 * 1024)
1898
1934
  value = {}
1899
- value['type'] = 'text'
1900
- value['content'] = content.upper()
1935
+ value['type'] = 'float'
1936
+ value['content'] = megabytes
1901
1937
  return value
1902
1938
 
1903
- def v_random(self, v):
1904
- limit = self.getRuntimeValue(v['content'])
1939
+ def v_modification(self, v):
1940
+ fileName = self.getRuntimeValue(v['fileName'])
1941
+ ts = int(os.stat(fileName).st_mtime)
1905
1942
  value = {}
1906
1943
  value['type'] = 'int'
1907
- value['content'] = randrange(0, limit)
1944
+ value['content'] = ts
1908
1945
  return value
1909
1946
 
1910
1947
  def v_modulo(self, v):
@@ -1954,6 +1991,13 @@ class Core(Handler):
1954
1991
  value['type'] = 'text'
1955
1992
  return value
1956
1993
 
1994
+ def v_random(self, v):
1995
+ limit = self.getRuntimeValue(v['content'])
1996
+ value = {}
1997
+ value['type'] = 'int'
1998
+ value['content'] = randrange(0, limit)
1999
+ return value
2000
+
1957
2001
  def v_right(self, v):
1958
2002
  content = self.getRuntimeValue(v['content'])
1959
2003
  count = self.getRuntimeValue(v['count'])
@@ -1970,32 +2014,11 @@ class Core(Handler):
1970
2014
  value['content'] = round(math.sin(angle * 0.01745329) * radius)
1971
2015
  return value
1972
2016
 
1973
- def v_tan(self, v):
1974
- angle = self.getRuntimeValue(v['angle'])
1975
- radius = self.getRuntimeValue(v['radius'])
1976
- value = {}
1977
- value['type'] = 'int'
1978
- value['content'] = round(math.tan(angle * 0.01745329) * radius)
1979
- return value
1980
-
1981
- def v_timestamp(self, v):
1982
- value = {}
1983
- value['type'] = 'int'
1984
- fmt = v['format']
1985
- if fmt == None:
1986
- value['content'] = int(time.time())
1987
- else:
1988
- fmt = self.getRuntimeValue(fmt)
1989
- dt = self.getRuntimeValue(v['datime'])
1990
- spec = datetime.strptime(dt, fmt)
1991
- t = datetime.now().replace(hour=spec.hour, minute=spec.minute, second=spec.second, microsecond=0)
1992
- value['content'] = int(t.timestamp())
1993
- return value
1994
-
1995
- def v_today(self, v):
2017
+ def v_stringify(self, v):
2018
+ item = self.getRuntimeValue(v['content'])
1996
2019
  value = {}
1997
- value['type'] = 'int'
1998
- value['content'] = int(datetime.combine(datetime.now().date(),datetime.min.time()).timestamp())*1000
2020
+ value['type'] = 'text'
2021
+ value['content'] = json.dumps(item)
1999
2022
  return value
2000
2023
 
2001
2024
  def v_symbol(self, symbolRecord):
@@ -2014,39 +2037,45 @@ class Core(Handler):
2014
2037
  else:
2015
2038
  return None
2016
2039
 
2017
- def v_valueOf(self, v):
2018
- v = self.getRuntimeValue(v['content'])
2040
+ def v_tab(self, v):
2019
2041
  value = {}
2020
- value['type'] = 'int'
2021
- value['content'] = int(v)
2042
+ value['type'] = 'text'
2043
+ value['content'] = '\t'
2022
2044
  return value
2023
2045
 
2024
- def v_files(self, v):
2025
- v = self.getRuntimeValue(v['target'])
2046
+ def v_tan(self, v):
2047
+ angle = self.getRuntimeValue(v['angle'])
2048
+ radius = self.getRuntimeValue(v['radius'])
2026
2049
  value = {}
2027
- value['type'] = 'text'
2028
- value['content'] = os.listdir(v)
2050
+ value['type'] = 'int'
2051
+ value['content'] = round(math.tan(angle * 0.01745329) * radius)
2029
2052
  return value
2030
2053
 
2031
- def v_trim(self, v):
2032
- v = self.getRuntimeValue(v['content'])
2054
+ def v_timestamp(self, v):
2033
2055
  value = {}
2034
- value['type'] = 'text'
2035
- value['content'] = v.strip()
2056
+ value['type'] = 'int'
2057
+ fmt = v['format']
2058
+ if fmt == None:
2059
+ value['content'] = int(time.time())
2060
+ else:
2061
+ fmt = self.getRuntimeValue(fmt)
2062
+ dt = self.getRuntimeValue(v['datime'])
2063
+ spec = datetime.strptime(dt, fmt)
2064
+ t = datetime.now().replace(hour=spec.hour, minute=spec.minute, second=spec.second, microsecond=0)
2065
+ value['content'] = int(t.timestamp())
2036
2066
  return value
2037
2067
 
2038
- def v_weekday(self, v):
2068
+ def v_today(self, v):
2039
2069
  value = {}
2040
2070
  value['type'] = 'int'
2041
- value['content'] = datetime.today().weekday()
2071
+ value['content'] = int(datetime.combine(datetime.now().date(),datetime.min.time()).timestamp())*1000
2042
2072
  return value
2043
2073
 
2044
- def v_memory(self, v):
2045
- process: Process = Process(os.getpid())
2046
- megabytes: float = process.memory_info().rss / (1024 * 1024)
2074
+ def v_trim(self, v):
2075
+ v = self.getRuntimeValue(v['content'])
2047
2076
  value = {}
2048
- value['type'] = 'float'
2049
- value['content'] = megabytes
2077
+ value['type'] = 'text'
2078
+ value['content'] = v.strip()
2050
2079
  return value
2051
2080
 
2052
2081
  def v_type(self, v):
@@ -2067,12 +2096,24 @@ class Core(Handler):
2067
2096
  value['content'] = 'object'
2068
2097
  return value
2069
2098
 
2070
- def v_modification(self, v):
2071
- fileName = self.getRuntimeValue(v['fileName'])
2072
- ts = int(os.stat(fileName).st_mtime)
2099
+ def v_uppercase(self, v):
2100
+ content = self.getRuntimeValue(v['content'])
2101
+ value = {}
2102
+ value['type'] = 'text'
2103
+ value['content'] = content.upper()
2104
+ return value
2105
+
2106
+ def v_valueOf(self, v):
2107
+ v = self.getRuntimeValue(v['content'])
2073
2108
  value = {}
2074
2109
  value['type'] = 'int'
2075
- value['content'] = ts
2110
+ value['content'] = int(v)
2111
+ return value
2112
+
2113
+ def v_weekday(self, v):
2114
+ value = {}
2115
+ value['type'] = 'int'
2116
+ value['content'] = datetime.today().weekday()
2076
2117
  return value
2077
2118
 
2078
2119
  #############################################################################
@@ -2170,20 +2211,59 @@ class Core(Handler):
2170
2211
  return True if condition.negate else False
2171
2212
  return False
2172
2213
 
2173
- def c_numeric(self, condition):
2174
- comparison = type(self.getRuntimeValue(condition.value1)) is int
2214
+ def c_empty(self, condition):
2215
+ value = self.getRuntimeValue(condition.value1)
2216
+ if value == None:
2217
+ comparison = True
2218
+ else:
2219
+ comparison = len(value) == 0
2175
2220
  return not comparison if condition.negate else comparison
2176
2221
 
2177
- def c_string(self, condition):
2178
- comparison = type(self.getRuntimeValue(condition.value1)) is str
2179
- return not comparison if condition.negate else comparison
2222
+ def c_ends(self, condition):
2223
+ value1 = self.getRuntimeValue(condition.value1)
2224
+ value2 = self.getRuntimeValue(condition.value2)
2225
+ return value1.endswith(value2)
2226
+
2227
+ def c_even(self, condition):
2228
+ return self.getRuntimeValue(condition.value1) % 2 == 0
2229
+
2230
+ def c_exists(self, condition):
2231
+ path = self.getRuntimeValue(condition.path)
2232
+ return os.path.exists(path)
2233
+
2234
+ def c_greater(self, condition):
2235
+ comparison = self.program.compare(condition.value1, condition.value2)
2236
+ return comparison <= 0 if condition.negate else comparison > 0
2237
+
2238
+ def c_hasProperty(self, condition):
2239
+ value = self.getRuntimeValue(condition.value1)
2240
+ prop = self.getRuntimeValue(condition.property)
2241
+ try:
2242
+ value[prop]
2243
+ hasProp = True
2244
+ except:
2245
+ hasProp = False
2246
+ return hasProp
2247
+
2248
+ def c_includes(self, condition):
2249
+ value1 = self.getRuntimeValue(condition.value1)
2250
+ value2 = self.getRuntimeValue(condition.value2)
2251
+ return value2 in value1
2252
+
2253
+ def c_is(self, condition):
2254
+ comparison = self.program.compare(condition.value1, condition.value2)
2255
+ return comparison != 0 if condition.negate else comparison == 0
2256
+
2257
+ def c_less(self, condition):
2258
+ comparison = self.program.compare(condition.value1, condition.value2)
2259
+ return comparison >= 0 if condition.negate else comparison < 0
2180
2260
 
2181
2261
  def c_list(self, condition):
2182
2262
  comparison = type(self.getRuntimeValue(condition.value1)) is list
2183
2263
  return not comparison if condition.negate else comparison
2184
2264
 
2185
- def c_object(self, condition):
2186
- comparison = type(self.getRuntimeValue(condition.value1)) is dict
2265
+ def c_numeric(self, condition):
2266
+ comparison = type(self.getRuntimeValue(condition.value1)) is int
2187
2267
  return not comparison if condition.negate else comparison
2188
2268
 
2189
2269
  def c_none(self, condition):
@@ -2193,58 +2273,19 @@ class Core(Handler):
2193
2273
  def c_not(self, condition):
2194
2274
  return not self.getRuntimeValue(condition.value1)
2195
2275
 
2196
- def c_even(self, condition):
2197
- return self.getRuntimeValue(condition.value1) % 2 == 0
2276
+ def c_object(self, condition):
2277
+ comparison = type(self.getRuntimeValue(condition.value1)) is dict
2278
+ return not comparison if condition.negate else comparison
2198
2279
 
2199
2280
  def c_odd(self, condition):
2200
2281
  return self.getRuntimeValue(condition.value1) % 2 == 1
2201
2282
 
2202
- def c_is(self, condition):
2203
- comparison = self.program.compare(condition.value1, condition.value2)
2204
- return comparison != 0 if condition.negate else comparison == 0
2205
-
2206
- def c_greater(self, condition):
2207
- comparison = self.program.compare(condition.value1, condition.value2)
2208
- return comparison <= 0 if condition.negate else comparison > 0
2209
-
2210
- def c_less(self, condition):
2211
- comparison = self.program.compare(condition.value1, condition.value2)
2212
- return comparison >= 0 if condition.negate else comparison < 0
2213
-
2214
2283
  def c_starts(self, condition):
2215
2284
  value1 = self.getRuntimeValue(condition.value1)
2216
2285
  value2 = self.getRuntimeValue(condition.value2)
2217
2286
  return value1.startswith(value2)
2218
2287
 
2219
- def c_ends(self, condition):
2220
- value1 = self.getRuntimeValue(condition.value1)
2221
- value2 = self.getRuntimeValue(condition.value2)
2222
- return value1.endswith(value2)
2223
-
2224
- def c_includes(self, condition):
2225
- value1 = self.getRuntimeValue(condition.value1)
2226
- value2 = self.getRuntimeValue(condition.value2)
2227
- return value2 in value1
2228
-
2229
- def c_empty(self, condition):
2230
- value = self.getRuntimeValue(condition.value1)
2231
- if value == None:
2232
- comparison = True
2233
- else:
2234
- comparison = len(value) == 0
2288
+ def c_string(self, condition):
2289
+ comparison = type(self.getRuntimeValue(condition.value1)) is str
2235
2290
  return not comparison if condition.negate else comparison
2236
-
2237
- def c_exists(self, condition):
2238
- path = self.getRuntimeValue(condition.path)
2239
- return os.path.exists(path)
2240
-
2241
- def c_hasProperty(self, condition):
2242
- value = self.getRuntimeValue(condition.value1)
2243
- prop = self.getRuntimeValue(condition.property)
2244
- try:
2245
- value[prop]
2246
- hasProp = True
2247
- except:
2248
- hasProp = False
2249
- return hasProp
2250
2291
  # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
easycoder/ec_program.py CHANGED
@@ -192,11 +192,11 @@ class Program:
192
192
  index = 0
193
193
  symbolRecord['value'][index] = value
194
194
 
195
- def encode(self, value):
196
- return value
195
+ def encode(self, value, encoding='UTF-8'):
196
+ return value.encode(encoding)
197
197
 
198
- def decode(self, value):
199
- return value
198
+ def decode(self, value, encoding='UTF-8'):
199
+ return value.decode(encoding)
200
200
 
201
201
  # Tokenise the script
202
202
  def tokenise(self, script):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: easycoder
3
- Version: 241231.1
3
+ Version: 250103.1
4
4
  Summary: Rapid scripting in English
5
5
  Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
6
6
  Author-email: Graham Trott <gtanyware@gmail.com>
@@ -10,7 +10,7 @@ Requires-Dist: pytz
10
10
  Project-URL: Home, https://github.com/easycoder/easycoder-py
11
11
 
12
12
  # Introduction
13
- This is the Python version of **_EasyCoder_**, a high-level English-like scripting language suited for prototyping and rapid testing of ideas. It operates on the command line.
13
+ **_EasyCoder_** is a high-level English-like scripting language suited for prototyping and rapid testing of ideas. It operates on the command line and a graphics module is under construction. This version of the language is written in Python and its runtime acts as a fairly thin wrapper around Python functions, giving good performance for general applications.
14
14
 
15
15
  The JavaScript version of **_EasyCoder_**, which provides a full set of graphical features to run in a browser, is at
16
16
 
@@ -31,7 +31,7 @@ This is traditionally the first program to be written in virtually any language.
31
31
  The output will look like this:
32
32
 
33
33
  ```
34
- EasyCoder version 5
34
+ EasyCoder version 250101.1
35
35
  Compiled <anon>: 1 lines (2 tokens) in 0 ms
36
36
  Run <anon>
37
37
  1-> Hello, world!
@@ -43,28 +43,28 @@ It's conventional to add a program title to a script:
43
43
  script Test
44
44
  print `Hello, world!`
45
45
  ```
46
- The first line here is just a comment and has no effect on the running of the script. The second line gives the script a name, which is useful in debugging as it says which script was running. When run, the output is now
46
+ The first line here is just a comment and has no effect on the running of the script. The second line gives the script a name, which is useful in debugging as it says which script was running. When run, the output is now
47
47
 
48
48
  ```
49
- EasyCoder version 5
50
- Compiled Test: 5 lines (4 tokens) in 0 ms
49
+ EasyCoder version 250101.1
50
+ Compiled Test: 3 lines (4 tokens) in 0 ms
51
51
  Run Test
52
- 5-> Hello, world!
52
+ 3-> Hello, world!
53
53
  ```
54
- As you can guess from the above, the print command gives the line in the script it was called from. This is very useful in tracking down debugging print commands in large scripts.
54
+ As you might guess from the above, the print command shows the line in the script it was called from. This is very useful in tracking down debugging print commands in large scripts.
55
55
 
56
56
  Here in the repository is a folder called `scripts` containing some sample scripts:
57
57
 
58
- `benchmark.ecs` allows the performance of EasyCoder to be compared to other languages if a similar program is written for each one
59
- `tests.ecs` is a test program containing many of the EasyCoder features
60
- `fizzbuzz.ecs` is a simple programming challenge often given at job interviews
58
+ `fizzbuzz.ecs` is a simple programming challenge often given at job interviews
59
+ `tests.ecs` is a test program containing many of the **_EasyCoder_** features
60
+ `benchmark.ecs` allows the performance of **_EasyCoder_** to be compared to other languages if a similar script is written for each one.
61
61
 
62
62
  ## Graphical programmming
63
- **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run a script using `easycoder {scriptname}.ecg`.
63
+ **_EasyCoder_** includes a graphical programming environment that is in the early stages of development. A couple of demo scripts are included in the `scripts` directory. To run them, first install the Python `kivy` graphics library if it's not already present on your system. This is done with `pip install kivy`. Then run your **_EasyCoder_** script using `easycoder {scriptname}.ecg`.
64
64
 
65
- Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment (but graphics will of course not be available in the former).
65
+ Graphical scripts look much like any other script but their file names must use the extension `.ecg` to signal to **_EasyCoder_** that it needs to load the graphics module. Non-graphical applications can use any extension but `.ecs` is recommended. This allows the **_EasyCoder_** application to be used wherever Python is installed, in either a command-line or a graphical environment, but graphics will of course not be available in the former.
66
66
 
67
- A couple of demo scripts are included in the `scripts` directory:
67
+ A couple of demo graphical scripts are included in the `scripts` directory:
68
68
 
69
69
  `graphics-demo.ecg` shows some of the elements that can be created, and demonstrates a variety of the graphical features of the language such as detecting when elements are clicked.
70
70
 
@@ -72,11 +72,9 @@ A couple of demo scripts are included in the `scripts` directory:
72
72
 
73
73
  **_EasyCoder_** graphics are handled by a library module, `ec_renderer` that can be used outside of the **_EasyCoder_** environment, in other Python programs.
74
74
 
75
- ## EasyCoder programming reference
75
+ ## Programming reference
76
76
 
77
- The language comprises a general-purpose core package, which can be enhanced by plugins to provide special features on demand.
78
-
79
- [The core package](doc/README.md)
77
+ **_EasyCoder_** comprises a set of modules to handle tokenisation, compilation and runtime control. Syntax and grammar are defined by [packages](doc/README.md), of which there are currently two; the [core](doc/core/README.md) package, which implements a comprehensive set of command-line programming features, and and the [graphics](doc/graphics/README.md) package, which adds graphical features in a windowing environment.
80
78
 
81
79
  ## Extending the language
82
80
 
@@ -1,19 +1,19 @@
1
1
  easycoder/README.md,sha256=PYqOc_SkIGiFbyCNs90y7JqoqWe4aO1xYIW-6bOnFKU,573
2
- easycoder/__init__.py,sha256=WpuFq9C1_LWCjt7667A94jo8QMavAs_jT2qZluZgT2E,283
2
+ easycoder/__init__.py,sha256=5hieaJUWovLn09r1Tf2I2hBLjfYGXMKuBb6usyd9sYc,283
3
3
  easycoder/ec.py,sha256=Nj5PRl8GsKjfGJKq0FOM1a7FeK3cN68CoIFg8lswQEg,221
4
4
  easycoder/ec_classes.py,sha256=xnWBNak8oKydkFoxHLlq9wo3lIsB3aMnTDrqbtCfoWo,1512
5
5
  easycoder/ec_compiler.py,sha256=2r6Nk7px9UMYqIpYc6dAbYOAFu-CoWPy-iqlsed49Lo,4690
6
6
  easycoder/ec_condition.py,sha256=WSbONo4zs2sX1icOVpscZDFSCAEFmTsquoc2RGcLx_k,763
7
- easycoder/ec_core.py,sha256=HtJWpfwz1eon0o4ZFYVM42ECAD6sKT8izvHYIb7dnv8,77463
7
+ easycoder/ec_core.py,sha256=1rYUGd5EXpjJkfYnnvJNjvMD_JfTGZRMEV0lLbYrzAU,78939
8
8
  easycoder/ec_graphics.py,sha256=o70BdQ-Y3uIo5nheQYwJUmM3gYVerKD9_5arQ8JTP-Y,15556
9
9
  easycoder/ec_handler.py,sha256=IJvxcrJJSR53d6DS_8H5qPHKhp9y5-GV4WXAjhZxu_o,2250
10
- easycoder/ec_program.py,sha256=6jK4blJMcRbspUEh-AW5MUVuLtLP023sZAbbgvPad-Y,8615
10
+ easycoder/ec_program.py,sha256=TUKQo56vURtx_UO7avIJZhz0EeOe2lNxQQz8EOOnCZ4,8685
11
11
  easycoder/ec_renderer.py,sha256=ejVFemHGuFBwGA__6VfZQZeZMnw4Ilvf_y9I34k04LM,7981
12
12
  easycoder/ec_screenspec.py,sha256=TeXgccfYoE--r7Rf9t9drV1V3fU-p-iBnZwtjHzIh8M,2524
13
13
  easycoder/ec_timestamp.py,sha256=_3QFJPzIWZ9Rzk3SQOQJ-gwmvB07pg78k23SPntoZtY,288
14
14
  easycoder/ec_value.py,sha256=XIBtGhcCgh1abrzAn-Wy4l_xH_3cTWakMVIiSlBAZjM,2386
15
- easycoder-241231.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
16
- easycoder-241231.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
17
- easycoder-241231.1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
18
- easycoder-241231.1.dist-info/METADATA,sha256=MhsFB-Ftja3Q0DFD-IomqX4Sntipma64e6WIUXyfXdQ,4605
19
- easycoder-241231.1.dist-info/RECORD,,
15
+ easycoder-250103.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
16
+ easycoder-250103.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
17
+ easycoder-250103.1.dist-info/WHEEL,sha256=ssQ84EZ5gH1pCOujd3iW7HClo_O_aDaClUbX4B8bjKY,100
18
+ easycoder-250103.1.dist-info/METADATA,sha256=6X8NoMG3Px2cLNDqWYxoMfki71O06qYk8qILNM_49VI,5178
19
+ easycoder-250103.1.dist-info/RECORD,,