Skip to content

Commit b836dbf

Browse files
authored
Add REPL mode and __scope__ debugging statement
Also fixed loading multiple programs, thanks to @testitem
1 parent a901f8a commit b836dbf

File tree

1 file changed

+69
-21
lines changed

1 file changed

+69
-21
lines changed

logicode.py

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
if not hasattr(__builtins__, 'basestring'):
1010
__builtins__.basestring = str
1111

12+
rLinestart = re.compile("^", re.M)
13+
rGetParentFunctionName = re.compile("<function ([^.]+)")
14+
15+
def getParentFunctionName(lambda_function):
16+
return rGetParentFunctionName.match(repr(lambda_function)).group(1)
17+
18+
def islambda(v):
19+
LAMBDA = lambda:0
20+
return isinstance(v, type(LAMBDA)) and v.__name__ == LAMBDA.__name__
1221

1322
class Scope:
1423
def __init__(self, parent={}):
@@ -38,6 +47,23 @@ def __delitem__(self, key):
3847
else:
3948
del self.parent[key]
4049

50+
def __repr__(self):
51+
string = "{"
52+
for key in self.lookup:
53+
value = self.lookup[key]
54+
string += "%s: %s" % (key,
55+
(getParentFunctionName(value) if
56+
islambda(value) else
57+
"".join(list(map(str, value))) if
58+
isinstance(value, list) else
59+
repr(value))
60+
)
61+
string += ", "
62+
string = string[:-2] + "}"
63+
return (string +
64+
"\n" +
65+
rLinestart.sub(" ", repr(self.parent)))
66+
4167
def has(self, key):
4268
return key in self
4369

@@ -59,9 +85,10 @@ def Inject(scope, keys, values):
5985
rWhitespace = re.compile(r"[ \t]+", re.M)
6086
rNewlines = re.compile(r"[\r\n]+", re.M)
6187
rBits = re.compile(r"[01]+")
62-
rName = re.compile(r"(?!\binput\b)[A-Z_$]+", re.I)
88+
rName = re.compile(r"(?!\binput\b|\b__scope__\b)[a-zA-Z_$]+")
6389
rRandom = re.compile(r"\?")
6490
rInput = re.compile(r"\binput\b")
91+
rScope = re.compile(r"\b__scope__\b")
6592
rInfix = re.compile(r"[&|]")
6693
rPrefix = re.compile(r"!")
6794
rPostfix = re.compile(r"\[[ht]\]")
@@ -84,7 +111,8 @@ def Inject(scope, keys, values):
84111
"Name": [rName],
85112
"Random": [rRandom],
86113
"Input": [rInput],
87-
"Literal": [["|", "Input", "Bits", "Name", "Random"]],
114+
"Scope": [rScope],
115+
"Literal": [["|", "Input", "Scope", "Bits", "Name", "Random"]],
88116
"Arguments": [
89117
rOpenParenthesis,
90118
["?", rName, ["*", rComma, rName]],
@@ -138,7 +166,8 @@ def Inject(scope, keys, values):
138166
"Condition",
139167
"Out",
140168
"Comment",
141-
"Newlines"
169+
"Newlines",
170+
"Expression"
142171
]
143172
]
144173
]
@@ -170,6 +199,10 @@ def Input(result):
170199
return lambda scope: [GetInput(scope)]
171200

172201

202+
def ScopeTransform(result):
203+
return lambda scope: Print(repr(scope))
204+
205+
173206
def Literal(result):
174207
return [result]
175208

@@ -286,14 +319,16 @@ def GetInput(scope):
286319

287320

288321
def Print(result):
289-
print("".join(list(map(str, result))))
322+
if result:
323+
print("".join(list(map(str, result))))
290324

291325
transform = {
292326
"Newlines": NoLambda,
293327
"Bits": Bits,
294328
"Name": Name,
295329
"Random": Random,
296330
"Input": Input,
331+
"Scope": ScopeTransform,
297332
"Literal": Literal,
298333
"Arguments": Arguments,
299334
"Call Arguments": Arguments,
@@ -327,7 +362,7 @@ def NoTransform(token, argument):
327362
return argument
328363

329364

330-
def get(code, token, process=Transform):
365+
def Get(code, token, process=Transform):
331366
length = 0
332367
match = rWhitespace.match(code)
333368
if match:
@@ -339,7 +374,7 @@ def get(code, token, process=Transform):
339374
rest = token[1:]
340375
if first == "|":
341376
for token in rest:
342-
result = get(code, token, process)
377+
result = Get(code, token, process)
343378
if result[0] != None:
344379
return (result[0], result[1] + length)
345380
return (None, 0)
@@ -355,7 +390,7 @@ def get(code, token, process=Transform):
355390
tokens = []
356391
success = True
357392
for token in rest:
358-
gotten = get(code, token, process)
393+
gotten = Get(code, token, process)
359394
if gotten[0] == None:
360395
success = False
361396
break
@@ -374,7 +409,7 @@ def get(code, token, process=Transform):
374409
result = []
375410
grammar = grammars[token]
376411
for tok in grammar:
377-
gotten = get(code, tok, process)
412+
gotten = Get(code, tok, process)
378413
if gotten[0] == None:
379414
return (None, 0)
380415
result += [gotten[0]]
@@ -390,22 +425,29 @@ def get(code, token, process=Transform):
390425
return (None, 0)
391426

392427

393-
def Run(code, input="", astify=False, grammar="Program"):
394-
scope = Scope()
428+
def Run(code="", input="", astify=False, grammar="Program", repl=False, scope=None):
429+
if not scope:
430+
scope = Scope()
431+
if repl:
432+
while repl:
433+
try:
434+
Print(Run(raw_input("Logicode> "), scope=scope))
435+
except (KeyboardInterrupt, EOFError):
436+
return
395437
scope["input"] = list(map(int, filter(
396438
lambda c: c == "0" or c == "1",
397439
input
398440
)))[::-1]
399441
if astify:
400-
result = get(code, grammar, NoTransform)[0]
442+
result = Get(code, grammar, NoTransform)[0]
401443
print(Astify(result))
402444
return
403-
result = get(code, grammar)[0]
445+
result = Get(code, grammar)[0]
404446
if result:
405447
program = result[0]
406448
for statement in program:
407-
function = statement[0]
408-
statement[0](scope)
449+
result = statement[0](scope)
450+
return result
409451

410452

411453
def Astify(parsed, padding=""):
@@ -427,17 +469,22 @@ def Astify(parsed, padding=""):
427469
help="Code of the program.")
428470
parser.add_argument("-i", "--input", type=str, nargs="?", default="",
429471
help="Input to the program.")
430-
parser.add_argument("-a", "--astify", action="store_true")
472+
parser.add_argument("-a", "--astify", action="store_true",
473+
help="Print AST instead of interpreting.")
474+
parser.add_argument("-r", "--repl", action="store_true",
475+
help="Open as REPL instead of interpreting.")
431476
argv = parser.parse_args()
432-
if len(argv.file):
477+
if argv.repl:
478+
Run(repl=True)
479+
elif len(argv.file):
433480
code = ""
434481
for path in argv.file:
435482
if os.path.isfile(argv.file[0]):
436483
with open(argv.file[0]) as file:
437-
code += file.read()
484+
code += file.read() + "\n"
438485
else:
439486
with open(argv.file[0] + ".lgc") as file:
440-
code += file.read()
487+
code += file.read() + "\n"
441488
if argv.astify:
442489
Run(code, "", True)
443490
elif argv.input:
@@ -452,9 +499,10 @@ def Astify(parsed, padding=""):
452499
else:
453500
Run(code)
454501
else:
502+
code = raw_input("Enter program: ")
455503
if argv.astify:
456-
Run(raw_input("Enter program: "), "", True)
504+
Run(code, "", True)
457505
elif argv.input:
458-
Run(raw_input("Enter program: "), argv.input[0])
506+
Run(code, argv.input[0])
459507
else:
460-
Run(raw_input("Enter program: "))
508+
Run(code)

0 commit comments

Comments
 (0)