Change eval from a special form to a function

This commit is contained in:
Kodi Arfer 2017-06-22 11:23:16 -07:00
parent 2e465dbf70
commit ca95194240
7 changed files with 40 additions and 51 deletions

1
NEWS
View File

@ -4,6 +4,7 @@ Changes from 0.13.0
* Single-character "sharp macros" changed to "tag macros", which can have * Single-character "sharp macros" changed to "tag macros", which can have
longer names longer names
* Periods are no longer allowed in keywords * Periods are no longer allowed in keywords
* `eval` is now a function instead of a special form
[ Bug Fixes ] [ Bug Fixes ]
* Numeric literals are no longer parsed as symbols when followed by a dot * Numeric literals are no longer parsed as symbols when followed by a dot

View File

@ -863,27 +863,6 @@ doto
=> collection => collection
[2 1] [2 1]
eval
----
``eval`` evaluates a quoted expression and returns the value. The optional
second and third arguments specify the dictionary of globals to use and the
module name. The globals dictionary defaults to ``(local)`` and the module name
defaults to the name of the current module.
.. code-block:: clj
=> (eval '(print "Hello World"))
"Hello World"
If you want to evaluate a string, use ``read-str`` to convert it to a
form first:
.. code-block:: clj
=> (eval (read-str "(+ 1 1)"))
2
eval-and-compile eval-and-compile
---------------- ----------------

View File

@ -230,6 +230,30 @@ Returns ``True`` if *coll* is empty. Equivalent to ``(= 0 (len coll))``.
False False
.. _eval-fn:
eval
----
``eval`` evaluates a quoted expression and returns the value. The optional
second and third arguments specify the dictionary of globals to use and the
module name. The globals dictionary defaults to ``(local)`` and the module name
defaults to the name of the current module.
.. code-block:: clj
=> (eval '(print "Hello World"))
"Hello World"
If you want to evaluate a string, use ``read-str`` to convert it to a
form first:
.. code-block:: clj
=> (eval (read-str "(+ 1 1)"))
2
.. _every?-fn: .. _every?-fn:
every? every?

View File

@ -706,31 +706,6 @@ class HyASTCompiler(object):
raise HyTypeError(expr, raise HyTypeError(expr,
"`%s' can't be used at the top-level" % expr[0]) "`%s' can't be used at the top-level" % expr[0])
@builds("eval")
@checkargs(min=1, max=3)
def compile_eval(self, expr):
expr.pop(0)
if not isinstance(expr[0], (HyExpression, HySymbol)):
raise HyTypeError(expr, "expression expected as first argument")
elist = [HySymbol("hy_eval")] + [expr[0]]
if len(expr) >= 2:
elist.append(expr[1])
else:
elist.append(HyExpression([HySymbol("locals")]))
if len(expr) == 3:
elist.append(expr[2])
else:
elist.append(HyString(self.module_name))
ret = self.compile(HyExpression(elist).replace(expr))
ret.add_imports("hy.importer", ["hy_eval"])
return ret
@builds("do") @builds("do")
def compile_do(self, expression): def compile_do(self, expression):
expression.pop(0) expression.pop(0)

View File

@ -19,6 +19,7 @@
(import [hy.models [HyCons HySymbol HyKeyword]]) (import [hy.models [HyCons HySymbol HyKeyword]])
(import [hy.lex [LexException PrematureEndOfInput tokenize]]) (import [hy.lex [LexException PrematureEndOfInput tokenize]])
(import [hy.compiler [HyASTCompiler]]) (import [hy.compiler [HyASTCompiler]])
(import [hy.importer [hy-eval :as eval]])
(defn butlast [coll] (defn butlast [coll]
"Returns coll except of last element." "Returns coll except of last element."
@ -469,7 +470,7 @@
(def *exports* (def *exports*
'[*map accumulate butlast calling-module-name chain coll? combinations '[*map accumulate butlast calling-module-name chain coll? combinations
comp complement compress cons cons? constantly count cycle dec distinct comp complement compress cons cons? constantly count cycle dec distinct
disassemble drop drop-last drop-while empty? even? every? first filter disassemble drop drop-last drop-while empty? eval even? every? first filter
flatten float? fraction gensym group-by identity inc input instance? flatten float? fraction gensym group-by identity inc input instance?
integer integer? integer-char? interleave interpose islice iterable? integer integer? integer-char? interleave interpose islice iterable?
iterate iterator? juxt keyword keyword? last list* macroexpand iterate iterator? juxt keyword keyword? last list* macroexpand

View File

@ -14,6 +14,7 @@ import struct
import imp import imp
import sys import sys
import ast import ast
import inspect
import os import os
import __future__ import __future__
@ -142,7 +143,14 @@ def import_buffer_to_module(module_name, buf):
return mod return mod
def hy_eval(hytree, namespace, module_name, ast_callback=None): def hy_eval(hytree, namespace=None, module_name=None, ast_callback=None):
if namespace is None:
frame = inspect.stack()[1][0]
namespace = inspect.getargvalues(frame).locals
if module_name is None:
m = inspect.getmodule(inspect.stack()[1][0])
module_name = '__eval__' if m is None else m.__name__
foo = HyObject() foo = HyObject()
foo.start_line = 0 foo.start_line = 0
foo.end_line = 0 foo.end_line = 0

View File

@ -1087,10 +1087,11 @@
(defn test-eval-failure [] (defn test-eval-failure []
"NATIVE: test eval failure modes" "NATIVE: test eval failure modes"
; yo dawg ; yo dawg
(try (eval '(eval)) (except [e HyTypeError]) (else (assert False))) (import [hy.compiler [HyCompileError]])
(try (eval '(eval "snafu")) (except [e HyTypeError]) (else (assert False))) (try (eval '(eval)) (except [e TypeError]) (else (assert False)))
(try (eval '(eval "snafu")) (except [e HyCompileError]) (else (assert False)))
(try (eval 'False []) (except [e HyTypeError]) (else (assert False))) (try (eval 'False []) (except [e HyTypeError]) (else (assert False)))
(try (eval 'False {} 1) (except [e HyTypeError]) (else (assert False)))) (try (eval 'False {} 1) (except [e TypeError]) (else (assert False))))
(defn test-import-syntax [] (defn test-import-syntax []