I'm trying to edit Norvig's lispy.py scheme-to-python interpreter for a racket program in which, in addition to the procedures he includes, I use open-input-string and string-replace.
It looked like I could just add the corresponding python definitions into his add_globals() function, which I did, as follows.
def add_globals(self):
"Add some Scheme standard procedures."
import math, cmath, operator as op
self.update(vars(math))
self.update(vars(cmath))
self.update({
'+':op.add, '-':op.sub, '*':op.mul, '/':op.div, 'not':op.not_,
'>':op.gt, '<':op.lt, '>=':op.ge, '<=':op.le, '=':op.eq,
'equal?':op.eq, 'eq?':op.is_, 'length':len, 'cons':cons,
'car':lambda x:x[0], 'cdr':lambda x:x[1:], 'append':op.add,
'list':lambda *x:list(x), 'list?': lambda x:isa(x,list),
'null?':lambda x:x==[], 'symbol?':lambda x: isa(x, Symbol),
'boolean?':lambda x: isa(x, bool), 'pair?':is_pair,
'port?': lambda x:isa(x,file), 'apply':lambda proc,l: proc(*l),
'eval':lambda x: eval(expand(x)), 'load':lambda fn: load(fn), 'call/cc':callcc,
'open-input-file':open,'close-input-port':lambda p: p.file.close(),
'open-output-file':lambda f:open(f,'w'), 'close-output-port':lambda p: p.close(),
'eof-object?':lambda x:x is eof_object, 'read-char':readchar,
# Additions below
'open-input-string':lambda x:x.decode('string_escape'),
'string-replace':lambda strng,x,y: strng.replace(x, y),
# Additions above
'read':read, 'write':lambda x,port=sys.stdout:port.write(to_string(x)),
'display':lambda x,port=sys.stdout:port.write(x if isa(x,str) else to_string(x))})
return self
However, when I try to use the racket functions in question, I get the following error from norvig's lispy repl:
% python lispy.py
Lispy version 2.0
lispy> (define (ex s)
(read (open-input-string (string-replace (string-replace s "\'" "\"") "," ""))))
lispy> (define inputlistsliceexample
(ex "[0, 0, 1, 0, 1, 1, 0, 1, 0, 0]"))
AttributeError: 'str' object has no attribute 'next_token'
lispy>
Then, if I get rid of my use of open-input-string in the definition for ex, I get the following interaction:
% python lispy.py
Lispy version 2.0
lispy> (define (exnihilo s)
(string-replace (string-replace s "\'" "\"") "," ""))
lispy> (define inputlistsliceexample
(exnihilo "[0, 0, 1, 0, 1, 1, 0, 1, 0, 0]"))
lispy> inputsliceexample
LookupError: inputsliceexample
Presumably I'm oversimplifying the process, but before I really dig into the rest lispy.py, I'd like to ask here to see whether the bug is superficially visible in what I added.
Edit:
Here are is my current add_globals:
def add_globals(self):
"Add some Scheme standard procedures."
import math, cmath, operator as op
self.update(vars(math))
self.update(vars(cmath))
self.update({
'+':op.add, '-':op.sub, '*':op.mul, '/':op.div, 'not':op.not_,
'>':op.gt, '<':op.lt, '>=':op.ge, '<=':op.le, '=':op.eq,
'equal?':op.eq, 'eq?':op.is_, 'length':len, 'cons':cons,
'car':lambda x:x[0], 'cdr':lambda x:x[1:], 'append':op.add,
'list':lambda *x:list(x), 'list?': lambda x:isa(x,list),
'null?':lambda x:x==[], 'symbol?':lambda x: isa(x, Symbol),
'boolean?':lambda x: isa(x, bool), 'pair?':is_pair,
'port?': lambda x:isa(x,file), 'apply':lambda proc,l: proc(*l),
'eval':lambda x: eval(expand(x)), 'load':lambda fn: load(fn), 'call/cc':callcc,
'open-input-file':open,'close-input-port':lambda p: p.file.close(),
'open-output-file':lambda f:open(f,'w'), 'close-output-port':lambda p: p.close(),
'eof-object?':lambda x:x is eof_object, 'read-char':readchar,
# Additions below
'string->jsexpr':lambda x: json.loads(x),
'string-replace':lambda strng,x,y: strng.replace(x, y),
# Additions above
'read':read, 'write':lambda x,port=sys.stdout:port.write(to_string(x)),
'display':lambda x,port=sys.stdout:port.write(x if isa(x,str) else to_string(x))})
return self
In the lispy repl, string-replace seems to succeed:
% python lispy.py
Lispy version 2.0
lispy> (string-replace "[['Noth', '<b>ing</b>'], ' in']" "\'" "\"")
"[[\"Noth\", \"<b>ing</b>\"], \" in\"]"
lispy>
However when, at the end of lispy.py, I run
if __name__ == '__main__':
x = eval(parse("""(begin
(string-replace "[['Noth', '<b>ing</b>'], ' in']" "\'" "\"")
)
"""
))
print x
instead of running this (which is how the file came),
if __name__ == '__main__':
repl()
the program hangs — and when I trace it, I see that there's an infinite loop.
Any ideas? (This is, I think, a more specific problem than my first one... I'm definitely feeling closer...)