SLet (Old 2)/Implementation: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
ZCX islptng (talk | contribs) No edit summary |
ZCX islptng (talk | contribs) Replaced content with "{{back|SLet}} NOT YET!" Tags: Replaced Reverted |
||
Line 1: | Line 1: | ||
{{back|SLet}} |
{{back|SLet}} |
||
NOT YET! |
|||
Save as <code>SLet.py</code><br> |
|||
There is no bug afaik. |
|||
<pre> |
|||
# SLet interpreter attempt |
|||
# by islptng |
|||
# https://esolangs.org/wiki/SLet |
|||
from math import floor |
|||
from random import randint |
|||
class Pair: |
|||
former = None |
|||
latter = None |
|||
def __init__(self, former, latter): |
|||
self.former = former |
|||
self.latter = latter |
|||
class Set: |
|||
content = [] |
|||
def __init__(self): |
|||
self.content = [] |
|||
def exist(self, value): |
|||
return value in self.content |
|||
def append(self, value): |
|||
if type(value) == Pair: |
|||
if value.latter == None: return |
|||
if not self.exist(value): |
|||
self.content.append(value) |
|||
def to_num(x): |
|||
if type(x) == int: |
|||
return x |
|||
elif type(x) == float: |
|||
return x |
|||
elif type(x) == Pair: |
|||
return x.former |
|||
elif type(x) == Set: |
|||
return len(x.content) |
|||
elif type(x) == str or type(x) == list: |
|||
return len(x) |
|||
def recursivenum(x): |
|||
while type(x) != int and type(x) != float: |
|||
x = to_num(x) |
|||
return x |
|||
self.content.sort(key=lambda x: recursivenum(x)) |
|||
def union(set1, set2): |
|||
result = Set() |
|||
try: |
|||
for x in set1.content: |
|||
result.append(x) |
|||
except: result.append(set1) |
|||
try: |
|||
for x in set2.content: |
|||
result.append(x) |
|||
except: result.append(set2) |
|||
return result |
|||
def intersect(set1, set2): |
|||
result = Set() |
|||
for x in set1.content: |
|||
if set2.exist(x): |
|||
result.append(x) |
|||
return result |
|||
def isfalse(x): |
|||
if type(x) == bool: |
|||
return not x |
|||
elif type(x) == int: |
|||
return x == 0 |
|||
elif type(x) == float: |
|||
return x == 0.0 |
|||
elif type(x) == Pair: |
|||
return isfalse(x.former) and isfalse(x.latter) |
|||
elif type(x) == Set: |
|||
return len(x.content) == 0 |
|||
def filter1(set1, condition): |
|||
result = Set() |
|||
for x in set1.content: |
|||
if not isfalse(condition(x)): |
|||
result.append(x) |
|||
return result |
|||
def pack(value): |
|||
result = Set() |
|||
result.append(value) |
|||
return result |
|||
def unpack(set1): |
|||
return set1.content[0] |
|||
def isnumber(x): |
|||
return type(x) == int or type(x) == float |
|||
def packifnum(x): |
|||
if isnumber(x): |
|||
return pack(x) |
|||
else: |
|||
return x |
|||
def plus(level, num1, num2): |
|||
if isnumber(num1) and isnumber(num2) and isnumber(level): |
|||
if level == 0: |
|||
return num1 + num2 |
|||
elif level == 1: |
|||
return num1 * num2 |
|||
elif level == 2: |
|||
return num1 ** num2 |
|||
result = num1 |
|||
for i in range(num2-1): |
|||
result = plus(level-1, result, result) |
|||
return result |
|||
result = Set() |
|||
for leveli in packifnum(level).content: |
|||
for num1i in packifnum(num1).content: |
|||
for num2i in packifnum(num2).content: |
|||
result.append(plus(leveli, num1i, num2i)) |
|||
return result |
|||
def negate(num): |
|||
if isnumber(num): |
|||
return -num |
|||
result = Set() |
|||
for numi in packifnum(num).content: |
|||
result.append(-numi) |
|||
return result |
|||
def divide(num): |
|||
if isnumber(num): |
|||
return 1/num |
|||
result = Set() |
|||
for numi in packifnum(num).content: |
|||
result.append(1/numi) |
|||
return result |
|||
def issubset(set1, set2): |
|||
for x in packifnum(set1).content: |
|||
if not set2.exist(x): |
|||
return False |
|||
return True |
|||
def analyze(srcstr): |
|||
class Tree: |
|||
content = [None] |
|||
depth = 0 |
|||
def dig(self): |
|||
res = self.content |
|||
for i in range(self.depth): res = res[-1] |
|||
res.pop() |
|||
res.append([None]) |
|||
self.depth += 1 |
|||
def push(self,val): |
|||
res = self.content |
|||
for i in range(self.depth): res = res[-1] |
|||
res.pop() |
|||
res.append(val) |
|||
res.append(None) |
|||
def pop(self): |
|||
res = self.content |
|||
for i in range(self.depth-1): res = res[-1] |
|||
res.append(None) |
|||
res = res[-2] |
|||
res.pop() |
|||
self.depth -= 1 |
|||
def finish(self): |
|||
res = self.content |
|||
for i in range(self.depth): res = res[-1] |
|||
res.pop() |
|||
return self.content |
|||
# the 1st step we get rid of quotes and comments |
|||
tcsrc = "" |
|||
incomment = False |
|||
inescape = False |
|||
intext = False |
|||
currentxt = "" |
|||
for i in srcstr: |
|||
if intext and not incomment: |
|||
if inescape: |
|||
inescape = False |
|||
if i == 'n': currentxt += chr(10) |
|||
elif i == 't': currentxt += '\t' |
|||
else: currentxt += i |
|||
else: |
|||
if i == '\\': |
|||
inescape = True |
|||
elif i == '!': |
|||
intext = False |
|||
tcsrc += '[' |
|||
for j in range(len(currentxt)-1): |
|||
tcsrc += str(ord(currentxt[j])) + ',' |
|||
tcsrc += str(ord(currentxt[len(currentxt)-1]))+'!' |
|||
else: currentxt += i |
|||
continue |
|||
if i == '(': |
|||
incomment = True |
|||
continue |
|||
if i == ')': |
|||
incomment = False |
|||
continue |
|||
if i == '"' and not incomment: |
|||
intext = True |
|||
currentxt = "" |
|||
continue |
|||
if incomment: continue |
|||
tcsrc += i |
|||
srcstr = tcsrc.replace("\t","").replace("\n","").replace(" ","") |
|||
srcstr = srcstr.replace("{","").replace("}","") # Don't forget we have no bracklets! |
|||
# the 2nd step we tokenize it |
|||
wdict = {'#':2,'@':1,'*':3,'~':2,';':0,':':1,"'":0,'`':1, |
|||
'|':-1,'&':-1,'^':1,'_':1,'=':1,'?':3,'+':3,'-':1,'/':1,'%':2,'<':1,'>':1,'$':2, |
|||
'[':-1,']':3,'\\':1,'!':0} |
|||
currentxt = "" |
|||
predlist = [] |
|||
for i in srcstr: |
|||
if i in wdict: |
|||
if currentxt != "": |
|||
predlist.append(currentxt) |
|||
currentxt = "" |
|||
predlist.append(i) |
|||
elif i == ',': |
|||
if currentxt != "": |
|||
predlist.append(currentxt) |
|||
currentxt = "" |
|||
else: |
|||
currentxt += i |
|||
# the 3rd step we analyze it |
|||
res = Tree() |
|||
tablist = [-1] |
|||
for i in predlist: |
|||
if i == '!': |
|||
tablist.pop() |
|||
res.pop() |
|||
while tablist[-1] == 0: |
|||
tablist.pop() |
|||
res.pop() |
|||
if i != '!': |
|||
tablist[-1] -= 1 |
|||
if i in wdict: |
|||
res.dig() |
|||
tablist.append(wdict[i]) |
|||
res.push(i) |
|||
return res.finish()[0] |
|||
def printable(val): |
|||
if type(val) == Set: |
|||
res = "{" |
|||
for i in val.content: |
|||
res += printable(i) + ", " |
|||
if res == "{": |
|||
return "Ø" |
|||
return res[:-2]+"}" |
|||
if type(val) == Pair: |
|||
return "(%s %s)" % (printable(val.former), printable(val.latter)) |
|||
return str(val) |
|||
class SLetProcedure: |
|||
variables = {} |
|||
def __init__(self,getchar,getnum,putchar,putnum): |
|||
self.getchar = getchar |
|||
self.getnum = getnum |
|||
self.putchar = putchar |
|||
self.putnum = putnum |
|||
def execute(self, instruction): |
|||
if type(instruction) == str: |
|||
try: |
|||
return int(instruction) |
|||
except: |
|||
try: |
|||
return float(instruction) |
|||
except: |
|||
if instruction in self.variables: |
|||
return self.variables[instruction] |
|||
else: |
|||
raise NameError("Undefined variable: "+instruction) |
|||
elif type(instruction) == list: |
|||
if type(instruction[0]) == list: |
|||
for i in instruction: |
|||
self.execute(i) |
|||
return None |
|||
if instruction[0] == '#': |
|||
self.variables[instruction[1]] = self.execute(instruction[2]) |
|||
elif instruction[0] == '@': |
|||
return self.execute(self.execute(instruction[1])) |
|||
elif instruction[0] == '*': |
|||
set1 = self.execute(instruction[1]) |
|||
inst = instruction[3][1:] |
|||
var = instruction[2] |
|||
for x in set1.content: |
|||
self.variables[var] = x |
|||
self.execute(inst) |
|||
elif instruction[0] == '~': |
|||
while not isfalse(self.execute(instruction[1])): |
|||
self.execute(self.execute(instruction[2])) |
|||
elif instruction[0] == ';': |
|||
self.getchar() |
|||
elif instruction[0] == ':': |
|||
self.putchar(self.execute(instruction[1])) |
|||
elif instruction[0] == "'": |
|||
return self.getnum() |
|||
elif instruction[0] == '`': |
|||
return self.putnum(self.execute(instruction[1])) |
|||
elif instruction[0] == '|': |
|||
result = Set() |
|||
for i in instruction[1:]: |
|||
result = union(result, self.execute(i)) |
|||
return result |
|||
elif instruction[0] == '&': |
|||
result = self.execute(instruction[1]) |
|||
for i in instruction[2:]: |
|||
result = intersect(result, self.execute(i)) |
|||
return result |
|||
elif instruction[0] == '^': |
|||
return pack(self.execute(instruction[1])) |
|||
elif instruction[0] == '_': |
|||
param = self.execute(instruction[1]) |
|||
try: |
|||
return unpack(param) |
|||
except: |
|||
if type(param) == int or type(param) == float: |
|||
return floor(param) |
|||
elif type(param) == Pair: |
|||
return randint(param.former, param.latter) |
|||
else: |
|||
raise TypeError("Cannot unpack non-set value: "+printable(param)) |
|||
elif instruction[0] == '=': |
|||
return len(self.execute(instruction[1]).content) |
|||
elif instruction[0] == '?': |
|||
set1 = self.execute(instruction[1]) |
|||
var = instruction[2] |
|||
# condition is a bit tricky, we need a lambda function to evaluate it |
|||
def condition(param): |
|||
self.variables[var] = param |
|||
return self.execute(instruction[3]) |
|||
return filter1(set1, condition) |
|||
elif instruction[0] == '+': |
|||
return plus(self.execute(instruction[1]), self.execute(instruction[2]), self.execute(instruction[3])) |
|||
elif instruction[0] == '-': |
|||
return negate(self.execute(instruction[1])) |
|||
elif instruction[0] == '/': |
|||
return divide(self.execute(instruction[1])) |
|||
elif instruction[0] == '%': |
|||
return Pair(self.execute(instruction[1]), self.execute(instruction[2])) |
|||
elif instruction[0] == '<': |
|||
return self.execute(instruction[1]).former |
|||
elif instruction[0] == '>': |
|||
return self.execute(instruction[1]).latter |
|||
elif instruction[0] == '$': |
|||
return issubset(self.execute(instruction[1]), self.execute(instruction[2])) |
|||
elif instruction[0] == '[': |
|||
result = Set() |
|||
for i in range(len(instruction)-1): |
|||
result.append(Pair(i, self.execute(instruction[i+1]))) |
|||
return result |
|||
elif instruction[0] == ']': |
|||
from1 = self.execute(instruction[1]) |
|||
to1 = self.execute(instruction[2]) |
|||
step1 = self.execute(instruction[3]) |
|||
if step1 > 0: judge = lambda a,b: a < b |
|||
else: judge = lambda a,b: a > b |
|||
result = Set() |
|||
while judge(from1,to1): |
|||
result.append(from1) |
|||
from1 += step1 |
|||
return result |
|||
elif instruction[0] == '\\': |
|||
if instruction[1][0] == '[': |
|||
return instruction[1][1:] |
|||
return instruction[1] |
|||
</pre> |
|||
IDLE: |
|||
<pre> |
|||
from SLet import * |
|||
inbuffer = "" |
|||
def iputchar(x): |
|||
print(chr(x), end="") |
|||
def iputnum(x): |
|||
print(x, end=" ") |
|||
def igetchar(): |
|||
global inbuffer |
|||
if len(inbuffer) == 0: |
|||
try: a = input() |
|||
except EOFError: a = "\0" |
|||
inbuffer += a + '\n' |
|||
t = inbuffer[0] |
|||
inbuffer = inbuffer[1:] |
|||
return t |
|||
def igetnum(): |
|||
global inbuffer |
|||
originalnum = "" |
|||
t = 'a' |
|||
while t not in '0123456789.': t = igetchar() |
|||
while t in '0123456789.': |
|||
originalnum += t |
|||
t = igetchar() |
|||
inbuffer = t + inbuffer |
|||
try: |
|||
return int(originalnum) |
|||
except: |
|||
return float(originalnum) |
|||
show = """SLet 2.0.1 - IDLE 1.0 (Nov.28 2024) by islptng |
|||
Type ".info" for the online document, |
|||
".def" to see a list of variables, |
|||
or ".exit" to quit. """ |
|||
print(show) |
|||
idle = SLetProcedure(igetchar,igetnum,iputchar,iputnum) |
|||
text = "" |
|||
while text != ".exit": |
|||
if text == ".def": |
|||
print("Name Value\n--------------------") |
|||
for i in idle.variables.keys(): |
|||
print(i,"\t",printable(idle.variables[i])) |
|||
print("--------------------") |
|||
text = "" |
|||
continue |
|||
elif text == ".info": |
|||
import webbrowser |
|||
webbrowser.open("https://esolangs.org/wiki/SLet") |
|||
text = "" |
|||
continue |
|||
try: |
|||
text = analyze("[" + text + "!") |
|||
error = True |
|||
try: |
|||
rtv = idle.execute(text) |
|||
error = False |
|||
except Exception as e: print(type(e),e) |
|||
if not error: |
|||
print("=",printable(rtv.content[0].latter)) |
|||
except: |
|||
pass |
|||
print("\n --> ", end="") |
|||
text = input() |
|||
</pre> |
Revision as of 23:44, 1 January 2025
← Back to SLet NOT YET!