Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control the use of the cl4py readtable. #9

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cl4py/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ def python_name(self):
else:
raise RuntimeError('Not a function name: {}'.format(self))

def __eq__(self, other) -> bool:
if isinstance(other, Cons):
return self.car == other.car and self.cdr == other.cdr
else:
return False


class ListIterator:
def __init__(self, elt):
Expand Down
54 changes: 28 additions & 26 deletions cl4py/py.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -766,31 +766,33 @@
(let* ((python (make-two-way-stream *standard-input* *standard-output*))
(lisp-output (make-string-output-stream))
(*standard-output* lisp-output)
(*trace-output* lisp-output)
(*readtable* *cl4py-readtable*))
(loop
(multiple-value-bind (value condition)
(handler-case (values (multiple-value-list (eval (read python))) nil)
(reader-error (c)
(clear-input python)
(values '() c))
(serious-condition (c)
(values '() c)))
(let ((*read-eval* nil)
(*print-circle* t))
;; First, write the name of the current package.
(pyprint (package-name *package*) python)
;; Second, write the obtained value.
(pyprint value python)
;; Third, write the obtained condition, or NIL.
(if (not condition)
(pyprint nil python)
(pyprint
(list (class-name (class-of condition))
(condition-string condition))
python))
;; Fourth, write the output that has been obtained so far.
(finish-output python)
(pyprint (get-output-stream-string lisp-output) python))))))
(*trace-output* lisp-output))
(flet ((read-python ()
(let ((*readtable* *cl4py-readtable*))
(read python))))
(loop
(multiple-value-bind (value condition)
(handler-case (values (multiple-value-list (eval (read-python))) nil)
(reader-error (c)
(clear-input python)
(values '() c))
(serious-condition (c)
(values '() c)))
(let ((*read-eval* nil)
(*print-circle* t))
;; First, write the name of the current package.
(pyprint (package-name *package*) python)
;; Second, write the obtained value.
(pyprint value python)
;; Third, write the obtained condition, or NIL.
(if (not condition)
(pyprint nil python)
(pyprint
(list (class-name (class-of condition))
(condition-string condition))
python))
;; Fourth, write the output that has been obtained so far.
(finish-output python)
(pyprint (get-output-stream-string lisp-output) python)))))))

(cl4py)
4 changes: 4 additions & 0 deletions test/sample-program.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(in-package :common-lisp-user)

(defun foo-{a7lkj9lakj} ()
nil)
39 changes: 39 additions & 0 deletions test/test_for_readtable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from pytest import fixture
import cl4py
import os

# pytest forces violation of this pylint rule
# pylint: disable=redefined-outer-name


@fixture(scope="module")
def lisp():
return cl4py.Lisp()


@fixture(scope="module")
def cl(lisp):
return lisp.function("find-package")("CL")


# This test verifies issue underlying MR #9
def test_readtable_problem(cl):
retval = cl.compile_file(
os.path.join(os.path.dirname(__file__), "sample-program.lisp")
)
outfile = os.path.join(os.path.dirname(__file__), "sample-program.fasl")
try:
assert retval[0] == outfile
assert os.path.exists(retval[0])
assert retval[1] == ()
assert retval[2] == ()
finally:
cleanup(outfile)
cleanup(outfile)

def cleanup(outfile):
if os.path.exists(outfile):
try:
os.remove(outfile)
except: # pylint: disable=bare-except
pass
62 changes: 62 additions & 0 deletions test/test_from_readme.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from pytest import fixture
import fractions

import cl4py
from cl4py import List, Symbol

# pytest forces violation of this pylint rule
# pylint: disable=redefined-outer-name

@fixture(scope="module")
def lisp():
return cl4py.Lisp()


@fixture(scope="module")
def cl(lisp):
return lisp.function("find-package")("CL")


def test_startup(lisp):
assert isinstance(lisp, cl4py.Lisp)


def test_examples(lisp):
assert lisp.eval(("+", 2, 3)) == 5
add = lisp.function("+")
assert add(1, 2, 3, 4) == 10
div = lisp.function("/")
assert div(2, 4) == fractions.Fraction(1, 2)
assert lisp.eval(cl4py.Symbol("*PRINT-BASE*", "COMMON-LISP")) == 10
assert lisp.eval(("CONS", 1, 2)) == cl4py.Cons(1, 2)
lst = lisp.eval(("CONS", 1, ("CONS", 2, ())))
assert lst == cl4py.List(1, 2)
assert lst.car == 1
assert lst.cdr == cl4py.List(2)
assert list(lst) == [1, 2]
assert sum(lst) == 3


def test_finding_functions(cl):
assert cl.oddp(5)
assert cl.cons(5, None) == cl4py.List(5)
assert cl.remove(5, [1, -5, 2, 7, 5, 9], key=cl.abs) == [1, 2, 7, 9]


def test_pythony_names(cl):
assert cl.type_of("foo") == List(
Symbol("SIMPLE-ARRAY", "COMMON-LISP"),
Symbol("CHARACTER", "COMMON-LISP"),
List(3),
)


def test_higher_order(cl):
assert cl.mapcar(cl.constantly(4), (1, 2, 3)) == List(4, 4, 4)


def test_circular_objects(cl, lisp):
twos = cl.cons(2, 2)
twos.cdr = twos
assert cl.mapcar(lisp.function("+"), (1, 2, 3, 4), twos) == \
List(3, 4, 5, 6)