Fix #1243: read raises EOFError on false inputs (#1244)

* Fix #1243: `read` raises EOFError on false inputs

* Fix crash when trying to `eval` false values
This commit is contained in:
Kodi Arfer 2017-03-06 08:51:25 -08:00 committed by Ryan Gonzalez
parent 8b6a45e43a
commit 5f00921dea
4 changed files with 42 additions and 16 deletions

2
NEWS
View File

@ -15,6 +15,8 @@ Changes from 0.12.1
* Shadowed comparison operators now use `and` instead of `&`
for chained comparisons
* partition no longer prematurely exhausts input iterators
* read and read-str no longer raise an error when the input
parses to a false value (e.g., the empty string)
Changes from 0.12.0

View File

@ -24,9 +24,9 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
from hy.models import (HyExpression, HyKeyword, HyInteger, HyComplex, HyString,
HyBytes, HySymbol, HyFloat, HyList, HySet, HyDict,
HyCons)
from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
HyString, HyBytes, HySymbol, HyFloat, HyList, HySet,
HyDict, HyCons)
from hy.errors import HyCompileError, HyTypeError
from hy.lex.parser import hy_symbol_mangle
@ -2689,7 +2689,10 @@ def hy_compile(tree, module_name, root=ast.Module, get_expr=False):
body = []
expr = None
if tree:
if not (isinstance(tree, HyObject) or type(tree) is list):
raise HyCompileError("tree must be a HyObject or a list")
if isinstance(tree, HyObject) or tree:
compiler = HyASTCompiler(module_name)
result = compiler.compile(tree)
expr = result.force_expr
@ -2697,10 +2700,9 @@ def hy_compile(tree, module_name, root=ast.Module, get_expr=False):
if not get_expr:
result += result.expr_as_stmt()
if isinstance(tree, list):
spoof_tree = tree[0]
else:
spoof_tree = tree
# We need to test that the type is *exactly* `list` because we don't
# want to do `tree[0]` on HyList or such.
spoof_tree = tree[0] if type(tree) is list else tree
body = compiler.imports_as_stmts(spoof_tree) + result.stmts
ret = root(body=body)

View File

@ -435,17 +435,17 @@
[eof ""]]
"Read from input and returns a tokenized string.
Can take a given input buffer to read from"
(def buff "")
(setv buff "")
(while True
(def inn (str (.readline from-file)))
(setv inn (string (.readline from-file)))
(if (= inn eof)
(raise (EOFError "Reached end of file" )))
(setv buff (+ buff inn))
(raise (EOFError "Reached end of file")))
(+= buff inn)
(try
(def parsed (first (tokenize buff)))
(setv parsed (first (tokenize buff)))
(except [e [PrematureEndOfInput IndexError]])
(else (if parsed (break)))))
parsed)
(else (break))))
parsed)
(defn read-str [input]
"Reads and tokenizes first line of input"

View File

@ -1055,6 +1055,19 @@
(assert (= None (eval (quote (print ""))))))
(defn test-eval-false []
(assert (is (eval 'False) False))
(assert (is (eval 'None) None))
(assert (= (eval '0) 0))
(assert (= (eval '"") ""))
(assert (= (eval 'b"") b""))
(assert (= (eval ':) :))
(assert (= (eval '[]) []))
(assert (= (eval '(,)) (,)))
(assert (= (eval '{}) {}))
(assert (= (eval '#{}) #{})))
(defn test-eval-globals []
"NATIVE: test eval with explicit global dict"
(assert (= 'bar (eval (quote foo) {'foo 'bar})))
@ -1383,7 +1396,16 @@
(defn test-read-str []
"NATIVE: test read-str"
(assert (= (read-str "(print 1)") '(print 1))))
(assert (= (read-str "(print 1)") '(print 1)))
(assert (is (type (read-str "(print 1)")) (type '(print 1))))
; Watch out for false values: https://github.com/hylang/hy/issues/1243
(assert (= (read-str "\"\"") '""))
(assert (is (type (read-str "\"\"")) (type '"")))
(assert (= (read-str "[]") '[]))
(assert (is (type (read-str "[]")) (type '[])))
(assert (= (read-str "0") '0))
(assert (is (type (read-str "0")) (type '0))))
(defn test-keyword-creation []
"NATIVE: Test keyword creation"