Expression?

This commit is contained in:
Simon Forman 2022-04-04 07:58:22 -07:00
parent 6eff23b191
commit 1da997fbbf
2 changed files with 87 additions and 0 deletions

View File

@ -0,0 +1,25 @@
class Expression:
def __init__(self, initial_expression=()):
self.current = initial_expression
self.stack = []
def __next__(self):
if self.current:
item, self.current = self.current
return item
if self.stack:
self.current = self.stack.pop()
return self.__next__()
raise StopIteration
def prepend(self, quoted_program):
if self.current:
self.stack.append(self.current)
self.current = quoted_program
from parser import text_to_expression as j
e = Expression(j('23 18'))

62
implementations/expr.py Normal file
View File

@ -0,0 +1,62 @@
from itertools import chain
from joy.utils.stack import _s, iter_stack
class Expression:
'''
As elegant as it is to model the expression as a stack, it's not very
efficient, as concatenating definitions and other quoted programs to
the expression is a common and expensive operation.
Instead, let's keep a stack of sub-expressions, reading from them
one-by-one, and prepending new sub-expressions to the stack rather than
concatenating them.
'''
def __init__(self, initial_expression=()):
self.current = initial_expression
self.stack = []
def __iter__(self):
return self
def __next__(self):
if self.current: (item, self.current) = self.current
elif self.stack: (item, self.current) = self.stack.pop()
else: raise StopIteration
return item
def prepend(self, quoted_program):
if not quoted_program: return
if self.current: self.stack.append(self.current)
self.current = quoted_program
def __str__(self):
return ' '.join(
map(
_s,
chain.from_iterable(
map(
iter_stack,
reversed(self.stack + [self.current])
)
)
)
)
if __name__ == '__main__':
from joy.parser import text_to_expression as j
e = Expression(j('23 18'))
e.prepend(j('88 19'))
e.prepend(j('foo fie feum'))
print(e)
for i in e:
print(i, e.stack, e.current)
if i == 88:
print('prepending "hello world"')
e.prepend(j('hello world'))
if i == 19:
print('prepending "good bye"')
e.prepend(j('good bye'))