Skip to content
GitLab
Explore
Sign in
Commits on Source (7)
commented out all dbg.p call while chasing repl call circle
· 12808585
Juergen Nickelsen
authored
Oct 08, 2017
12808585
current state of broken things
· 6c8219d8
Juergen Nickelsen
authored
Oct 12, 2017
6c8219d8
removed a meaningless (ah!) blank line
· 4868125e
Juergen Nickelsen
authored
Oct 14, 2017
4868125e
don't let macros have an own environment (they shouldn't)
· 19823702
Juergen Nickelsen
authored
Oct 14, 2017
19823702
comment out the test (one of a few, really) that makes pyle crash
· cb5d99fc
Juergen Nickelsen
authored
Oct 14, 2017
cb5d99fc
Merge branch 'master' into detour/repr-crash
· e823ac17
Juergen Nickelsen
authored
May 28, 2018
e823ac17
fix using the readline library for interactive input
· c5f22c21
Juergen Nickelsen
authored
May 28, 2018
c5f22c21
Show whitespace changes
Inline
Side-by-side
Makefile
View file @
c5f22c21
...
...
@@ -11,7 +11,7 @@ all:
@
echo
test
:
./pyle
-e
tests.l < data.l
./pyle
-
s
e
tests.l < data.l
tags
:
*.py
etags
*
.py
*
.l
...
...
basedefs.l
View file @
c5f22c21
;;; base macros and functions for pyle
(defmacro defun (symbol args . bodyforms)
"Define a function named SYMBOL with ARGS list and BODYFORMS."
(let ((funcsym (gensym)))
`(let ((,funcsym (lambda ,args ,@bodyforms)))
(putprop ',symbol ,funcsym 'sys:function)
(set-function-name ,funcsym ',symbol))))
;; (defun car (l)
;; (let (((first) l))
;; first))
;; (defun cdr (l)
;; (let (((first . rest) l))
;; rest))
(defmacro setq (var value)
`(set ',var ,value))
...
...
@@ -119,13 +134,6 @@ symbol definition chain explicitly."
(defmacro symbol-name (sym)
`(string ,sym))
(defmacro defun (symbol args . bodyforms)
"Define a function named SYMBOL with ARGS list and BODYFORMS."
(let ((funcsym (gensym)))
`(let ((,funcsym (lambda ,args ,@bodyforms)))
(putprop ',symbol ,funcsym 'sys:function)
(set-function-name ,funcsym ',symbol))))
(defmacro dolist ((var listform resultform) . bodyforms)
"Iterate over LISTFORM, binding symbol VAR to each element in turn.
Return the value of RESULTFORM (if specified) or nil."
...
...
@@ -198,14 +206,12 @@ FROM, TO, STEP, and TEST are evaluated just once."
(defmacro incf (place . rest)
"Increment PLACE by optional DELTA (or 1) and return the new value."
(let (((delta) rest))
(if delta
`(setf ,place (+ ,place ,delta))
`(setf ,place (1+ ,place)))))
(let ((delta (or (car rest) 1)))
`(setf ,place (+ ,place ,delta))))
(defmacro decf (place . rest)
"Decrement place by optional DELTA (or 1) and return the new value."
(let ((
(
delta
)
rest))
(let ((delta
(car
rest))
)
(if delta
`(setf ,place (- ,place ,delta))
`(setf ,place (1- ,place)))))
...
...
@@ -479,9 +485,11 @@ bigger than the previous one by optional STEP (default 1)."
(defun list-length (l)
"Return the length of list L."
(if (null l)
0
(+ 1 (list-length (cdr l)))))
(let ((len 0))
(while l
(pop l)
(incf len))
len))
(defun length (ob)
"Return the length of string or list OB."
...
...
builtin.py
View file @
c5f22c21
...
...
@@ -322,8 +322,8 @@ def Pyle_let(arglist):
savedEnv
=
enterEnvironment
()
try
:
bindings
,
bodyforms
=
arglist
.
cxr
()
dbg
.
p
(
dbg
.
let
,
"
bindings:
"
,
bindings
)
dbg
.
p
(
dbg
.
let
,
"
body:
"
,
bodyforms
)
#
dbg.p(dbg.let, "bindings:", bindings)
#
dbg.p(dbg.let, "body:", bodyforms)
params
=
ListCollector
()
args
=
ListCollector
()
for
binding
in
bindings
:
...
...
@@ -352,8 +352,8 @@ def Pyle_letrec(arglist):
savedEnv
=
enterEnvironment
()
try
:
bindings
,
bodyforms
=
arglist
.
cxr
()
dbg
.
p
(
dbg
.
let
,
"
bindings:
"
,
bindings
)
dbg
.
p
(
dbg
.
let
,
"
body:
"
,
bodyforms
)
#
dbg.p(dbg.let, "bindings:", bindings)
#
dbg.p(dbg.let, "body:", bodyforms)
params
=
ListCollector
()
# need them in proper order
args
=
ListCollector
()
for
binding
in
bindings
:
...
...
@@ -397,6 +397,13 @@ def Pyle_macroexpand(arglist):
"""
return
macroexpandForm
(
arglist
.
car
())
def
Pyle_macroexpand1
(
arglist
):
"""
@desc args: EXPR; result: expanded form
Expand one layer of macro calls in EXPR and return the expanded form.
"""
exp
,
hasepanded
=
expandFormRecurse
(
arglist
.
car
())
return
exp
def
Pyle_minus
(
arglist
):
"""
@desc name: -; args: NUMBER1 ...; result: subtraction
Subtract the number arguments from the first.
...
...
@@ -527,7 +534,7 @@ def Pyle_read(arglist):
else
:
port
=
sys
.
stdin
fname
=
"
*stdin*
"
rdr
=
reader
.
Reader
(
port
,
fname
)
rdr
=
reader
.
Reader
(
port
,
fname
,
None
)
obj
=
rdr
.
read
()
rdr
.
close
()
return
obj
...
...
@@ -738,7 +745,7 @@ def make_builtin(func):
builtin_func
=
Builtin
(
builtin_name
,
func
,
minargs
,
maxargs
,
isspecial
)
sym
=
intern
(
builtin_name
)
sym
.
setFunction
(
builtin_func
)
dbg
.
p
(
dbg
.
bi
,
"
builtin
"
,
sym
,
minargs
,
maxargs
,
sym
.
getFunction
())
#
dbg.p(dbg.bi, "builtin", sym, minargs, maxargs, sym.getFunction())
# must copy this to avoid "RuntimeError: dictionary changed size
# during iteration" :-(
...
...
eval.py
View file @
c5f22c21
...
...
@@ -12,14 +12,14 @@ import dep
from
utils
import
*
def
evalProgn
(
oblist
):
dbg
.
p
(
dbg
.
eval
,
"
evalprogn
"
,
oblist
)
#
dbg.p(dbg.eval, "evalprogn", oblist)
result
=
Nil
for
ob
in
oblist
:
result
=
Eval
(
ob
)
return
result
def
evalFun
(
funob
):
dbg
.
p
(
dbg
.
eval
,
"
evalFun
"
,
funob
)
#
dbg.p(dbg.eval, "evalFun", funob)
if
funob
.
isSymbol
():
func
=
funob
.
getFunction
()
if
func
:
...
...
@@ -31,13 +31,13 @@ def evalFun(funob):
raise
PyleNoFunctionError
(
funob
)
def
evalArgs
(
oblist
):
dbg
.
p
(
dbg
.
eval
,
"
evalargs
"
,
oblist
)
#
dbg.p(dbg.eval, "evalargs", oblist)
length
=
0
lc
=
ListCollector
()
for
ob
in
oblist
:
length
+=
1
lc
.
add
(
Eval
(
ob
))
dbg
.
p
(
dbg
.
eval
,
"
evalArgs returns
"
,
lc
.
list
(),
length
)
#
dbg.p(dbg.eval, "evalArgs returns", lc.list(), length)
return
lc
.
list
(),
length
level
=
0
...
...
@@ -50,8 +50,8 @@ def Eval(ob):
level
+=
1
envs
.
append
(
CurrentEnv
)
try
:
dbg
.
p
(
dbg
.
eval
,
"
{l}Eval {o} in {e}
"
.
format
(
o
=
ob
,
e
=
CurrentEnv
,
l
=
makeString
(
2
*
level
)))
#
dbg.p(dbg.eval, "{l}Eval {o} in {e}".format(o=ob, e=CurrentEnv,
#
l=makeString(2 * level)))
if
ob
.
isSymbol
():
result
=
ob
.
value
()
elif
ob
.
isPair
():
...
...
@@ -64,7 +64,7 @@ def Eval(ob):
result
=
function
.
call
(
arglist
,
length
)
else
:
result
=
ob
dbg
.
p
(
dbg
.
eval
,
"
{l}<= {r}
"
.
format
(
r
=
result
,
l
=
makeString
(
2
*
level
)))
#
dbg.p(dbg.eval, "{l}<= {r}".format(r=result, l=makeString(2 * level)))
return
result
except
PyleThrow
as
throw
:
raise
throw
...
...
macro.py
View file @
c5f22c21
...
...
@@ -9,25 +9,26 @@ import dep
from
object
import
*
from
stdsyms
import
*
def
expandList
(
list
):
# return new list, haveExpanded
dbg
.
p
(
dbg
.
mac
,
"
expandList:
"
,
list
)
def
expandList
(
list
,
level
):
# return new list, haveExpanded
#
dbg.p(dbg.mac, "expandList:", list)
haveExpanded
=
False
lc
=
ListCollector
()
# cannot use simple iteration over the list, which would not
# handle improper lists
while
list
.
isPair
():
elem
,
did
=
expandFormRecurse
(
list
.
car
())
elem
,
did
=
expandFormRecurse
(
list
.
car
()
,
level
)
lc
.
add
(
elem
)
haveExpanded
=
haveExpanded
or
did
list
=
list
.
cdr
()
if
list
:
# last cdr of improper list
elem
,
did
=
expandFormRecurse
(
list
)
elem
,
did
=
expandFormRecurse
(
list
,
level
)
lc
.
addEnd
(
elem
)
haveExpanded
=
haveExpanded
or
did
return
lc
.
list
(),
haveExpanded
def
expandFormRecurse
(
form
):
# return expanded form, haveExpanded
dbg
.
p
(
dbg
.
mac
,
"
expandFormRecurse:
"
,
form
)
def
expandFormRecurse
(
form
,
level
=
""
):
# return expanded form, haveExpanded
# print(level, "expandFormRecurse:", form)
# dbg.p(dbg.mac, "expandFormRecurse:", form)
if
form
.
isPair
():
head
=
form
.
car
()
if
head
.
isSymbol
():
...
...
@@ -35,15 +36,15 @@ def expandFormRecurse(form): # return expanded form, haveExpanded
maybeMacro
=
head
.
getFunction
()
if
maybeMacro
and
maybeMacro
.
isMacro
():
result
=
maybeMacro
.
expand
(
args
),
True
return
result
else
:
expargs
,
did
=
expandList
(
args
)
re
turn
cons
(
head
,
expargs
),
did
expargs
,
did
=
expandList
(
args
,
level
+
"
"
)
re
sult
=
cons
(
head
,
expargs
),
did
else
:
result
=
expandList
(
form
)
return
result
result
=
expandList
(
form
,
level
+
"
"
)
else
:
return
form
,
False
result
=
form
,
False
# print(level, "=>", result)
return
result
def
macroexpandForm
(
form
):
needExpand
=
True
...
...
object.py
View file @
c5f22c21
...
...
@@ -126,8 +126,8 @@ class Symbol(Object):
return
Symbol
(
name
)
def
__init__
(
self
,
name
,
immutable
=
False
,
selfval
=
False
):
dbg
.
p
(
dbg
.
sym
,
"
init Symbol({n}, imm={i}, self={s})
"
.
format
(
n
=
name
,
i
=
immutable
,
s
=
selfval
))
#
dbg.p(dbg.sym, "init Symbol({n}, imm={i}, self={s})".
#
format(n=name, i=immutable, s=selfval))
if
name
==
NamePropSymbolName
:
namesym
=
self
else
:
...
...
@@ -171,7 +171,7 @@ class Symbol(Object):
def
bind
(
self
,
ob
):
envbind
(
self
,
ob
)
def
boundp
(
self
):
dbg
.
p
(
dbg
.
sym
,
"
boundp
"
,
self
,
CurrentEnv
.
getvalOrNone
(
self
))
#
dbg.p(dbg.sym, "boundp", self, CurrentEnv.getvalOrNone(self))
return
CurrentEnv
.
getvalOrNone
(
self
)
is
not
None
def
value
(
self
):
return
envget
(
self
)
...
...
@@ -247,12 +247,11 @@ class Function(Object):
class
Macro
(
Function
):
def
__init__
(
self
,
name
,
params
,
body
):
self
.
env
=
CurrentEnv
self
.
name
=
name
self
.
params
=
params
self
.
minargs
=
params
.
lengthI
()
self
.
maxargs
=
self
.
minargs
if
params
.
isProper
()
else
None
dbg
.
p
(
dbg
.
form
,
name
,
"
has minargs
"
,
self
.
minargs
)
#
dbg.p(dbg.form, name, "has minargs", self.minargs)
self
.
special
=
False
maybeDocstring
,
restBody
=
body
.
cxr
()
...
...
@@ -273,16 +272,16 @@ class Macro(Function):
raise
PyleMacroCallError
(
self
.
name
)
def
expand
(
self
,
arglist
):
self
.
checkArgs
(
arglist
.
length
())
savedEnv
=
enterEnvironment
(
self
.
env
)
savedEnv
=
enterEnvironment
()
try
:
bind_params
(
self
.
params
,
arglist
,
self
.
name
)
dbg
.
p
(
dbg
.
call
,
"
evalProgn in
"
,
CurrentEnv
,
self
.
body
)
#
dbg.p(dbg.call, "evalProgn in", CurrentEnv, self.body)
return
dep
.
evalProgn
(
self
.
body
)
finally
:
backtoEnvironment
(
savedEnv
)
def
describe
(
self
):
return
p2l
({
"
type
"
:
self
.
__class__
.
__name__
,
"
id
"
:
id
(
self
),
"
env
"
:
self
.
env
,
"
name
"
:
self
.
name
,
"
params
"
:
self
.
params
,
"
name
"
:
self
.
name
,
"
params
"
:
self
.
params
,
"
minargs
"
:
Number
(
self
.
minargs
),
"
maxargs
"
:
Number
(
self
.
maxargs
),
"
synopsis
"
:
self
.
synopsis
(),
...
...
@@ -292,7 +291,7 @@ class Macro(Function):
# this is used for parameter bindings on function calls and variable
# bindings in let/let*; destructuring binds will go here, too
def
bind_params
(
params
,
args
,
function
=
None
,
needEval
=
False
,
strict
=
True
):
dbg
.
p
(
dbg
.
bind
,
"
bind_params:
"
,
params
,
args
,
function
,
needEval
)
#
dbg.p(dbg.bind, "bind_params:", params, args, function, needEval)
nargs
=
args
.
length
()
if
args
.
isList
()
else
1
while
params
.
isPair
()
and
args
.
isPair
():
param
,
params
=
params
.
cxr
()
...
...
@@ -304,7 +303,7 @@ def bind_params(params, args, function=None, needEval=False, strict=True):
if
param
.
isSymbol
():
if
param
is
Nil
:
continue
# skip bindings if param symbol is nil
dbg
.
p
(
dbg
.
bind
,
"
envbind:
"
,
param
,
arg
)
#
dbg.p(dbg.bind, "envbind:", param, arg)
envbind
(
param
,
arg
)
elif
param
.
isPair
():
bind_params
(
param
,
arg
,
function
,
False
,
False
)
...
...
@@ -315,7 +314,7 @@ def bind_params(params, args, function=None, needEval=False, strict=True):
return
# standard situation, proper params
# list, also with let and let*
elif
params
.
isSymbol
():
dbg
.
p
(
dbg
.
bind
,
"
envbind:
"
,
params
,
Nil
)
#
dbg.p(dbg.bind, "envbind:", params, Nil)
envbind
(
params
,
Nil
)
elif
strict
and
function
:
raise
PyleArgCountError
(
function
,
nargs
,
function
.
minargs
)
...
...
@@ -338,7 +337,7 @@ def bind_params(params, args, function=None, needEval=False, strict=True):
# improper arameter list
if
needEval
:
args
,
_
=
dep
.
evalList
(
args
)
dbg
.
p
(
dbg
.
bind
,
"
envbind:
"
,
params
,
args
)
#
dbg.p(dbg.bind, "envbind:", params, args)
envbind
(
params
,
args
)
else
:
assert
False
,
"
binding wtf 3? {f}: params {p}, args left {a}
"
.
\
...
...
@@ -352,7 +351,7 @@ class Form(Function):
self
.
params
=
params
self
.
minargs
=
params
.
lengthI
()
self
.
maxargs
=
self
.
minargs
if
params
.
isProper
()
else
None
dbg
.
p
(
dbg
.
form
,
name
,
"
has minargs
"
,
self
.
minargs
)
#
dbg.p(dbg.form, name, "has minargs", self.minargs)
self
.
special
=
False
maybeDocstring
,
restBody
=
body
.
cxr
()
...
...
@@ -375,7 +374,7 @@ class Form(Function):
savedEnv
=
enterEnvironment
(
self
.
env
)
try
:
bind_params
(
self
.
params
,
arglist
)
dbg
.
p
(
dbg
.
call
,
"
evalProgn in
"
,
CurrentEnv
,
self
.
body
)
#
dbg.p(dbg.call, "evalProgn in", CurrentEnv, self.body)
return
dep
.
evalProgn
(
self
.
body
)
finally
:
backtoEnvironment
(
savedEnv
)
...
...
@@ -401,8 +400,8 @@ class Builtin(Function):
self
.
_synopsis
=
doclines
[
0
]
def
call
(
self
,
arglist
,
nargs
):
self
.
checkArgs
(
nargs
)
dbg
.
p
(
dbg
.
call
,
"
call {s} with {a} [{n}]
"
.
format
(
s
=
self
,
a
=
arglist
,
n
=
nargs
))
#
dbg.p(dbg.call, "call {s} with {a} [{n}]".
#
format(s=self, a=arglist, n=nargs))
return
self
.
code
(
arglist
)
def
__str__
(
self
):
return
"
#<{s}>
"
.
format
(
s
=
self
.
synopsis
())
...
...
@@ -490,14 +489,14 @@ def enterEnvironment(parent=None):
parent
=
CurrentEnv
savedEnv
=
CurrentEnv
CurrentEnv
=
Environment
(
parent
)
dbg
.
p
(
dbg
.
env
,
"
enter environment
"
,
CurrentEnv
,
"
saved
"
,
savedEnv
,
"
parent
"
,
parent
)
#
dbg.p(dbg.env, "enter environment", CurrentEnv,
#
"saved", savedEnv, "parent", parent)
return
savedEnv
def
backtoEnvironment
(
env
):
global
CurrentEnv
assert
CurrentEnv
!=
RootEnv
dbg
.
p
(
dbg
.
env
,
"
drop environment
"
,
CurrentEnv
,
"
back to
"
,
env
)
#
dbg.p(dbg.env, "drop environment", CurrentEnv, "back to", env)
CurrentEnv
=
env
def
envbind
(
symbol
,
value
,
env
=
None
):
...
...
@@ -505,18 +504,18 @@ def envbind(symbol, value, env=None):
env
=
CurrentEnv
if
symbol
.
immutable
():
raise
PyleModifyImmutableError
(
symbol
)
dbg
.
p
(
dbg
.
env
,
"
bind {s} <= {v}
"
.
format
(
s
=
symbol
,
v
=
value
))
#
dbg.p(dbg.env, "bind {s} <= {v}".format(s=symbol, v=value))
env
.
bind
(
symbol
,
value
)
def
envget
(
symbol
,
env
=
None
):
global
CurrentEnv
if
not
env
:
env
=
CurrentEnv
dbg
.
p
(
dbg
.
env
,
"
envget
"
,
symbol
,
env
)
#
dbg.p(dbg.env, "envget", symbol, env)
return
env
.
getval
(
symbol
)
def
envset
(
symbol
,
value
,
env
=
None
):
dbg
.
p
(
dbg
.
env
,
"
envset
"
,
symbol
,
value
,
env
)
#
dbg.p(dbg.env, "envset", symbol, value, env)
if
env
is
None
:
env
=
CurrentEnv
if
symbol
.
immutable
():
...
...
@@ -527,11 +526,11 @@ def intern(name, immutable=False, selfval=False):
assert
str
(
name
)
!=
"
None
"
if
name
in
symbolTable
:
sym
=
symbolTable
[
name
]
dbg
.
p
(
dbg
.
sym
,
"
intern
"
,
name
,
"
has
"
,
sym
)
#
dbg.p(dbg.sym, "intern", name, "has", sym)
else
:
sym
=
Symbol
(
name
,
immutable
,
selfval
)
symbolTable
[
name
]
=
sym
dbg
.
p
(
dbg
.
sym
,
"
intern new
"
,
sym
)
#
dbg.p(dbg.sym, "intern new", sym)
return
sym
def
internSelf
(
name
):
...
...
@@ -607,7 +606,14 @@ class Pair(Object):
self
.
_cdr
=
cdr
def
dump
(
self
):
return
"
#<{n}:{s}>
"
.
format
(
n
=
self
.
__class__
.
__name__
,
s
=
self
)
def
__repr__
(
self
):
def
__repr__
(
self
,
obset
=
None
):
if
obset
is
None
:
# print("start anew with pair", id(self))
obset
=
set
()
# if self in obset:
# # print("already seen pair", id(self))
# return "<...>"
obset
.
add
(
self
)
result
=
[
"
(
"
]
current
=
self
first
=
True
...
...
@@ -617,6 +623,9 @@ class Pair(Object):
else
:
result
.
append
(
"
"
)
el
,
current
=
current
.
cxr
()
if
el
.
isPair
():
result
.
append
(
el
.
__repr__
(
obset
))
else
:
result
.
append
(
repr
(
el
))
if
current
is
not
Nil
:
result
.
append
(
"
.
"
)
...
...
@@ -679,11 +688,11 @@ class ListCollector():
def
__init__
(
self
):
self
.
_first
=
Nil
self
.
_last
=
Nil
dbg
.
p
(
dbg
.
lc
,
self
,
"
initialized with
"
,
self
.
_first
,
self
.
_last
)
#
dbg.p(dbg.lc, self, "initialized with", self._first, self._last)
def
__repr__
(
self
):
return
"
#<{n} {l}>
"
.
format
(
n
=
self
.
__class__
.
__name__
,
l
=
self
.
_first
)
def
add
(
self
,
ob
):
dbg
.
p
(
dbg
.
lc
,
"
lc gets
"
,
ob
)
#
dbg.p(dbg.lc, "lc gets", ob)
newcons
=
cons
(
ob
,
Nil
)
if
self
.
_first
is
Nil
:
self
.
_first
=
newcons
...
...
@@ -694,14 +703,14 @@ class ListCollector():
"
self._last._cdr is {0}
"
.
format
(
self
.
_last
.
_cdr
)
self
.
_last
.
rplacd
(
newcons
)
self
.
_last
=
newcons
dbg
.
p
(
dbg
.
lc
,
"
lc now has
"
,
self
.
_first
)
#
dbg.p(dbg.lc, "lc now has", self._first)
def
addEnd
(
self
,
ob
):
if
self
.
_first
:
self
.
_last
.
rplacd
(
ob
)
else
:
self
.
_first
=
ob
def
list
(
self
):
dbg
.
p
(
dbg
.
lc
,
"
lc returns
"
,
self
.
_first
)
#
dbg.p(dbg.lc, "lc returns", self._first)
return
self
.
_first
def
last
(
self
):
return
self
.
_last
...
...
@@ -716,7 +725,7 @@ def list(*args):
return
lc
.
list
()
def
init_env
():
dbg
.
p
(
dbg
.
env
,
"
init env
"
)
#
dbg.p(dbg.env, "init env")
global
RootEnv
RootEnv
=
Environment
()
global
CurrentEnv
...
...
pyle
View file @
c5f22c21
...
...
@@ -42,7 +42,7 @@ try:
except
get_opts
.
OptionError
as
e
:
sys
.
exit
(
program
+
"
:
"
+
str
(
e
)
+
"
\n
"
+
usage
)
dbg
.
p
(
dbg
.
main
,
sys
.
argv
[
0
],
"
starting up
"
)
#
dbg.p(dbg.main, sys.argv[0], "starting up")
for
flags
in
ovc
.
debugflags
:
for
flag
in
flags
.
split
(
"
,
"
):
...
...
@@ -67,11 +67,11 @@ for file in ovc.loadfiles:
if
len
(
argv
)
>
0
:
dbg
.
p
(
dbg
.
main
,
"
args are
"
,
argv
)
#
dbg.p(dbg.main, "args are", argv)
for
arg
in
argv
:
dbg
.
p
(
dbg
.
main
,
"
loading
"
,
arg
)
#
dbg.p(dbg.main, "loading", arg)
reader
.
loadFile
(
arg
)
else
:
dbg
.
p
(
dbg
.
main
,
"
starting interactive repl...
"
)
#
dbg.p(dbg.main, "starting interactive repl...")
reader
.
repl
(
sys
.
stdin
,
"
*stdin*
"
,
sys
.
stdout
)
reader.py
View file @
c5f22c21
...
...
@@ -22,7 +22,7 @@ suffixes = ['', '.l', str(base64.b64decode('Lmxpc3A='))]
def
loadFile
(
fname
,
missing_ok
=
False
):
try
:
dbg
.
p
(
dbg
.
load
,
"
try to load
"
,
fname
)
#
dbg.p(dbg.load, "try to load", fname)
with
open
(
str
(
fname
))
as
f
:
info
(
"
; loading
"
,
fname
)
dep
.
repl
(
f
,
fname
)
...
...
@@ -56,27 +56,29 @@ def load(name, missing_ok=False):
return
Nil
raise
PyleFileNotFoundError
(
str
(
name
),
load
=
True
)
def
is_interactive
(
in_port
,
out_port
):
return
in_port
.
isatty
()
and
out_port
and
out_port
.
isatty
()
def
repl
(
inp
,
fname
,
out
=
None
):
reader
=
Reader
(
inp
,
fname
)
dbg
.
p
(
dbg
.
repl
,
"
start repl on
"
,
fname
)
dep
.
interactive
=
inp
.
isatty
()
and
out
and
out
.
isatty
()
reader
=
Reader
(
inp
,
fname
,
out
)
# dbg.p(dbg.repl, "start repl on", fname)
try
:
while
True
:
if
de
p
.
interactive
:
if
rea
de
r
.
interactive
:
print
(
"
>
"
,
end
=
''
,
file
=
out
,
flush
=
True
)
ob
=
reader
.
read
()
if
ob
is
not
None
:
dbg
.
p
(
dbg
.
repl
,
"
=> {o} ({t})
"
.
format
(
o
=
ob
,
t
=
type
(
ob
)))
#
dbg.p(dbg.repl, "=> {o} ({t})".format(o=ob, t=type(ob)))
try
:
expr
=
macroexpandForm
(
ob
)
dbg
.
p
(
dbg
.
repl
,
"
exp {e} ({t})
"
.
format
(
e
=
expr
,
t
=
type
(
expr
)))
#
dbg.p(dbg.repl, "exp {e} ({t})".
#
format(e=expr, t=type(expr)))
value
=
Eval
(
expr
)
if
out
:
print
(
"
\n
"
+
repr
(
value
),
file
=
out
)
else
:
dbg
.
p
(
dbg
.
load
,
"
value:
"
,
value
)
# dbg.p(dbg.load, "value:", value)
pass
except
PyleThrow
as
e
:
print
(
"
\n
ERR throw without catch, tag: {t}; value: {v}
"
.
format
(
t
=
repr
(
e
.
tag
()),
v
=
repr
(
e
.
value
())))
...
...
@@ -90,7 +92,7 @@ def repl(inp, fname, out=None):
if
dep
.
exit_on_error
:
sys
.
exit
(
"
exit due to error
"
)
else
:
if
de
p
.
interactive
:
if
rea
de
r
.
interactive
:
print
(
file
=
out
)
return
finally
:
...
...
@@ -175,9 +177,20 @@ class StringPort():
substr
=
self
.
string
[
self
.
position
:
newpos
]
self
.
position
=
newpos
return
substr
def
readline
(
self
):
result
=
""
while
True
:
ch
=
self
.
read
(
1
)
if
not
ch
:
return
result
result
+=
ch
if
ch
==
"
\n
"
:
return
result
def
isatty
(
self
):
return
False
class
Reader
():
def
__init__
(
self
,
inp
,
fname
):
def
__init__
(
self
,
inp
,
fname
,
out
):
self
.
inp
=
inp
self
.
fname
=
fname
self
.
unreadchar
=
None
...
...
@@ -186,6 +199,7 @@ class Reader():
self
.
currentLine
=
None
self
.
lineLen
=
0
self
.
linePos
=
0
self
.
interactive
=
is_interactive
(
inp
,
out
)
def
close
(
self
):
pass
def
unread
(
self
,
ch
):
...
...
@@ -196,19 +210,18 @@ class Reader():
dbg
.
p
(
dbg
.
read
,
"
push back token
"
,
token
)
def
getline
(
self
):
"
Get a new line; return truish iff there was one.
"
if
dep
.
interactive
:
if
self
.
interactive
:
try
:
self
.
line
=
input
()
line
=
input
()
except
EOFError
:
return
False
self
.
line
+=
"
\n
"
line
+=
"
\n
"
else
:
self
.
line
=
self
.
inp
.
readline
()
print
(
self
.
line
)
self
.
currentLine
=
self
.
line
line
=
self
.
inp
.
readline
()
self
.
currentLine
=
line
self
.
linePos
=
0
self
.
lineLen
=
len
(
self
.
line
)
return
self
.
line
self
.
lineLen
=
len
(
line
)
return
line
def
getchar
(
self
):
if
self
.
linePos
>=
self
.
lineLen
:
hadOne
=
self
.
getline
()
...
...
@@ -270,7 +283,7 @@ class Reader():
result
=
QuasiquoteToken
()
else
:
result
=
self
.
collectAtom
(
ch
)
dbg
.
p
(
dbg
.
read
,
"
next token is
"
,
result
)
#
dbg.p(dbg.read, "next token is", result)
return
result
def
unquoteOrUnquoteSplicingToken
(
self
):
ch
=
self
.
nextChar
()
...
...
@@ -336,10 +349,10 @@ class Reader():
lc
=
ListCollector
()
while
True
:
t
=
self
.
nextToken
()
dbg
.
p
(
dbg
.
read
,
"
collectList sees
"
,
t
)
#
dbg.p(dbg.read, "collectList sees", t)
ttype
=
type
(
t
)
if
ttype
is
CparenToken
:
dbg
.
p
(
dbg
.
read
,
"
collectList done with
"
,
lc
.
list
())
#
dbg.p(dbg.read, "collectList done with", lc.list())
return
lc
.
list
()
if
ttype
is
DotToken
:
end
=
self
.
read
()
...
...
tests.l
View file @
c5f22c21
...
...
@@ -14,7 +14,7 @@
(exp (string ',expect))
(thename (string ',name)))
(setq testcount (1+ testcount))
(format t "{}: {} => {}\n" testcount thename value)
(format t "{}: {
:20
} => {}\n" testcount thename value)
;; (when (member thename test-names)
;; (format t "\nWARN test {} already seen\n" thename))
;; (push thename test-names)
...
...