gilch: We've got conflicting files now.

Auto-promotion sure seems like it would make some things easier.

How would this affect #919? Tag macros are still at compile time, but I think Clojure's tagged literals are at read time, like Common Lisp's `#.`. I'd also like easier access to Python's `eval` in Hy (we already have `exec`). Currently you have to import it from the `builtins` module. We could either rename Hy's eval (to `hy-eval`) or rename Python's eval (to `py-eval`). I'm imagining in-line Python--something like
```
=> (#py"lambda x: x + 1" 41)
42
```
--would be possible with no performance impact. Currently, even with a macro, the (py)eval has to happen at runtime.
gilch: If we're generally autoboxing unquotes, shouldn't this work?
```Python
=> (disassemble `(+ ~(+ 1 1) 40) True)
from hy.core.language import disassemble
from hy import HyExpression, HyInteger, HySymbol
disassemble(HyExpression(((([] + [HySymbol('+')]) + [(1 + 1)]) + [HyInteger(40)])), True)
Traceback (most recent call last):
  File "c:\users\me\documents\github\autobox-hy\hy\importer.py", line 184, in hy_eval
    return eval(ast_compile(expr, "<eval>", "eval"), namespace)
  File "<eval>", line 1, in <module>
  File "C:\Users\ME\Documents\GitHub\autobox-hy/hy/core/language.hy", line 78, in disassemble
    (fake-source-positions tree)
  File "C:\Users\ME\Documents\GitHub\autobox-hy/hy/core/language.hy", line 182, in fake_source_positions
    (fake-source-positions subtree)))
  File "C:\Users\ME\Documents\GitHub\autobox-hy/hy/core/language.hy", line 185, in fake_source_positions
    (setattr tree attr 1))))
AttributeError: 'int' object has no attribute 'start_line'
```
It works if I box it manually though.
```Python
=> (disassemble `(+ ~(HyInteger (+ 1 1)) 40) True)
from hy.core.language import disassemble
from hy import HyExpression, HyInteger, HySymbol
disassemble(HyExpression(((([] + [HySymbol('+')]) + [HyInteger((1 + 1))]) + [HyInteger(40)])), True)
'(2 + 40)'
```
Is the compiler really the right place to put this?
Kodiologist: I think #919 and inline Python (which I, too, would like to see) are orthogonal to this PR. And yeah, I think it would make sense to have `builtins.eval` exported from `hy.core.language` as `py-eval`, although that too would probably be better in a separate PR.

I'll look into the merge conflicts and `disassemble`. The latter is presumably running into problems because it does its own faking of source positions, which isn't playing nicely with how I do that in the compiler.

> Is the compiler really the right place to put this?

I'm pretty sure that the answer is yes. It's the last chance to do it, so doing it then should mean that we only have to implement it in one place in Hy.
diff --git a/NEWS b/NEWS
index b99e2285..a21c5142 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ Changes from 0.13.0
    * Single-character "sharp macros" changed to "tag macros", which can have
      longer names
    * Periods are no longer allowed in keywords
+   * `eval` is now a function instead of a special form
+   * The compiler now automatically promotes values to Hy model objects
+     as necessary, so you can write ``(eval `(+ 1 ~n))`` instead of
+     ``(eval `(+ 1 ~(HyInteger n)))``
 
    [ Bug Fixes ]
    * Numeric literals are no longer parsed as symbols when followed by a dot
diff --git a/docs/language/api.rst b/docs/language/api.rst
index 0058c7dc..5ed646d0 100644
--- a/docs/language/api.rst
+++ b/docs/language/api.rst
@@ -863,27 +863,6 @@ doto
   => collection
   [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
 ----------------
diff --git a/docs/language/core.rst b/docs/language/core.rst
index b52cef4d..21c111b4 100644
--- a/docs/language/core.rst
+++ b/docs/language/core.rst
@@ -230,6 +230,30 @@ Returns ``True`` if *coll* is empty. Equivalent to ``(= 0 (len coll))``.
    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?
diff --git a/hy/cmdline.py b/hy/cmdline.py
index 71e4b2c3..a9d966c0 100644
--- a/hy/cmdline.py
+++ b/hy/cmdline.py
@@ -15,7 +15,7 @@ import astor.codegen
 
 import hy
 
-from hy.lex import LexException, PrematureEndOfInput, tokenize
+from hy.lex import LexException, PrematureEndOfInput
 from hy.lex.parser import hy_symbol_mangle
 from hy.compiler import HyTypeError
 from hy.importer import (hy_eval, import_buffer_to_module,
@@ -77,12 +77,9 @@ class HyREPL(code.InteractiveConsole):
         global SIMPLE_TRACEBACKS
         try:
             try:
-                tokens = tokenize(source)
+                do = import_buffer_to_hst(source)
             except PrematureEndOfInput:
                 return True
-            do = HyExpression([HySymbol('do')] + tokens)
-            do.start_line = do.end_line = do.start_column = do.end_column = 1
-            do.replace(do)
         except LexException as e:
             if e.source is None:
                 e.source = source
diff --git a/hy/compiler.py b/hy/compiler.py
index 437495d8..adc26472 100755
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -5,14 +5,15 @@
 
 from hy.models import (HyObject, HyExpression, HyKeyword, HyInteger, HyComplex,
                        HyString, HyBytes, HySymbol, HyFloat, HyList, HySet,
-                       HyDict, HyCons)
+                       HyDict, HyCons, wrap_value)
 from hy.errors import HyCompileError, HyTypeError
 
 from hy.lex.parser import hy_symbol_mangle
 
 import hy.macros
 from hy._compat import (
-    str_type, bytes_type, long_type, PY3, PY34, PY35, raise_empty)
+    str_type, string_types, bytes_type, long_type, PY3, PY34, PY35,
+    raise_empty)
 from hy.macros import require, macroexpand, tag_macroexpand
 import hy.importer
 
@@ -110,6 +111,19 @@ def builds_if(_type, condition):
         return lambda fn: fn
 
 
+def spoof_positions(obj):
+    if not isinstance(obj, HyObject) or isinstance(obj, HyCons):
+        return
+    if not hasattr(obj, "start_column"):
+        obj.start_column = 0
+    if not hasattr(obj, "start_line"):
+        obj.start_line = 0
+    if (hasattr(obj, "__iter__") and
+            not isinstance(obj, (string_types, bytes_type))):
+        for x in obj:
+            spoof_positions(x)
+
+
 class Result(object):
     """
     Smart representation of the result of a hy->AST compilation
@@ -378,23 +392,23 @@ class HyASTCompiler(object):
         ret = Result()
         for module, names in self.imports.items():
             if None in names:
-                ret += self.compile([
-                    HyExpression([
+                e = HyExpression([
                         HySymbol("import"),
                         HySymbol(module),
                     ]).replace(expr)
-                ])
+                spoof_positions(e)
+                ret += self.compile(e)
             names = sorted(name for name in names if name)
             if names:
-                ret += self.compile([
-                    HyExpression([
+                e = HyExpression([
                         HySymbol("import"),
                         HyList([
                             HySymbol(module),
                             HyList([HySymbol(name) for name in names])
                         ])
                     ]).replace(expr)
-                ])
+                spoof_positions(e)
+                ret += self.compile(e)
         self.imports = defaultdict(set)
         return ret.stmts
 
@@ -404,6 +418,11 @@ class HyASTCompiler(object):
             if not isinstance(ret, Result):
                 ret = Result() + ret
             return ret
+        if not isinstance(atom, HyObject):
+            atom = wrap_value(atom)
+            if isinstance(atom, HyObject):
+                spoof_positions(atom)
+                return self.compile_atom(type(atom), atom)
 
     def compile(self, tree):
         try:
@@ -602,12 +621,6 @@ class HyASTCompiler(object):
         ast.copy_location(new_name, name)
         return new_name
 
-    @builds(list)
-    def compile_raw_list(self, entries):
-        ret = self._compile_branch(entries)
-        ret += ret.expr_as_stmt()
-        return ret
-
     def _render_quoted_form(self, form, level):
         """
         Render a quoted form as a new HyExpression.
@@ -706,31 +719,6 @@ class HyASTCompiler(object):
         raise HyTypeError(expr,
                           "`%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")
     def compile_do(self, expression):
         expression.pop(0)
@@ -766,6 +754,7 @@ class HyASTCompiler(object):
         return ret
 
     @builds("try")
+    @checkargs(min=2)
     def compile_try_expression(self, expr):
         expr.pop(0)  # try
 
@@ -1858,6 +1847,7 @@ class HyASTCompiler(object):
         op = ops[expression.pop(0)]
         right_associative = op == ast.Pow
 
+        lineno, col_offset = expression.start_line, expression.start_column
         if right_associative:
             expression = expression[::-1]
         ret = self.compile(expression.pop(0))
@@ -1870,8 +1860,8 @@ class HyASTCompiler(object):
             ret += ast.BinOp(left=left_expr,
                              op=op(),
                              right=right_expr,
-                             lineno=child.start_line,
-                             col_offset=child.start_column)
+                             lineno=lineno,
+                             col_offset=col_offset)
         return ret
 
     @builds("**")
@@ -2619,21 +2609,21 @@ def hy_compile(tree, module_name, root=ast.Module, get_expr=False):
     body = []
     expr = None
 
-    if not (isinstance(tree, HyObject) or type(tree) is list):
-        raise HyCompileError("tree must be a HyObject or a list")
+    if not isinstance(tree, HyObject):
+        tree = wrap_value(tree)
+        if not isinstance(tree, HyObject):
+            raise HyCompileError("`tree` must be a HyObject or capable of "
+                                 "being promoted to one")
+        spoof_positions(tree)
 
-    if isinstance(tree, HyObject) or tree:
-        compiler = HyASTCompiler(module_name)
-        result = compiler.compile(tree)
-        expr = result.force_expr
+    compiler = HyASTCompiler(module_name)
+    result = compiler.compile(tree)
+    expr = result.force_expr
 
-        if not get_expr:
-            result += result.expr_as_stmt()
+    if not get_expr:
+        result += result.expr_as_stmt()
 
-        # 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
+    body = compiler.imports_as_stmts(tree) + result.stmts
 
     ret = root(body=body)
 
diff --git a/hy/core/language.hy b/hy/core/language.hy
index d498c454..6bcdb793 100644
--- a/hy/core/language.hy
+++ b/hy/core/language.hy
@@ -18,7 +18,8 @@
 (import [hy._compat [long-type]]) ; long for python2, int for python3
 (import [hy.models [HyCons HySymbol HyKeyword]])
 (import [hy.lex [LexException PrematureEndOfInput tokenize]])
-(import [hy.compiler [HyASTCompiler]])
+(import [hy.compiler [HyASTCompiler spoof-positions]])
+(import [hy.importer [hy-eval :as eval]])
 
 (defn butlast [coll]
   "Returns coll except of last element."
@@ -74,8 +75,8 @@
   (import astor)
   (import hy.compiler)
 
-  (fake-source-positions tree)
-  (setv compiled (hy.compiler.hy_compile tree (calling-module-name)))
+  (spoof-positions tree)
+  (setv compiled (hy.compiler.hy-compile tree (calling-module-name)))
   ((if codegen
             astor.codegen.to_source
             astor.dump)
@@ -174,15 +175,6 @@
   "Return true if (pred x) is logical true for every x in coll, else false"
   (all (map pred coll)))
 
-(defn fake-source-positions [tree]
-  "Fake the source positions for a given tree"
-  (if (coll? tree)
-    (for* [subtree tree]
-          (fake-source-positions subtree)))
-  (for* [attr '[start-line end-line start-column end-column]]
-        (if (not (hasattr tree attr))
-          (setattr tree attr 1))))
-
 (defn flatten [coll]
   "Return a single flat list expanding all members of coll"
   (if (coll? coll)
@@ -469,7 +461,7 @@
 (def *exports*
   '[*map accumulate butlast calling-module-name chain coll? combinations
     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?
     integer integer? integer-char? interleave interpose islice iterable?
     iterate iterator? juxt keyword keyword? last list* macroexpand
diff --git a/hy/importer.py b/hy/importer.py
index ec3b606e..63b87d4a 100644
--- a/hy/importer.py
+++ b/hy/importer.py
@@ -3,7 +3,7 @@
 # license. See the LICENSE.
 
 from hy.compiler import hy_compile, HyTypeError
-from hy.models import HyObject, replace_hy_obj
+from hy.models import HyObject, HyExpression, HySymbol, replace_hy_obj
 from hy.lex import tokenize, LexException
 from hy.errors import HyIOError
 
@@ -14,6 +14,7 @@ import struct
 import imp
 import sys
 import ast
+import inspect
 import os
 import __future__
 
@@ -31,7 +32,7 @@ def ast_compile(ast, filename, mode):
 
 def import_buffer_to_hst(buf):
     """Import content from buf and return a Hy AST."""
-    return tokenize(buf + "\n")
+    return HyExpression([HySymbol("do")] + tokenize(buf + "\n"))
 
 
 def import_file_to_hst(fpath):
@@ -142,7 +143,27 @@ def import_buffer_to_module(module_name, buf):
     return mod
 
 
-def hy_eval(hytree, namespace, module_name, ast_callback=None):
+def hy_eval(hytree, namespace=None, module_name=None, ast_callback=None):
+    """``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.
+
+       => (eval '(print "Hello World"))
+       "Hello World"
+
+    If you want to evaluate a string, use ``read-str`` to convert it to a
+    form first:
+
+       => (eval (read-str "(+ 1 1)"))
+       2"""
+    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.start_line = 0
     foo.end_line = 0
diff --git a/hy/macros.py b/hy/macros.py
index b24735c2..874c63af 100644
--- a/hy/macros.py
+++ b/hy/macros.py
@@ -3,7 +3,7 @@
 # license. See the LICENSE.
 
 from inspect import getargspec, formatargspec
-from hy.models import replace_hy_obj, wrap_value, HyExpression, HyString
+from hy.models import replace_hy_obj, HyExpression, HyString
 
 from hy.errors import HyTypeError, HyMacroExpansionError
 
@@ -196,7 +196,7 @@ def macroexpand_1(tree, compiler):
                     raise HyMacroExpansionError(tree, msg)
 
                 try:
-                    obj = wrap_value(m(*ntree[1:], **opts))
+                    obj = m(*ntree[1:], **opts)
                 except HyTypeError as e:
                     if e.expression is None:
                         e.expression = tree
@@ -225,4 +225,4 @@ def tag_macroexpand(tag, tree, compiler):
             )
 
     expr = tag_macro(tree)
-    return replace_hy_obj(wrap_value(expr), tree)
+    return replace_hy_obj(expr, tree)
diff --git a/hy/models.py b/hy/models.py
index 412f5d1f..93cce18a 100644
--- a/hy/models.py
+++ b/hy/models.py
@@ -4,6 +4,7 @@
 
 from __future__ import unicode_literals
 from hy._compat import PY3, str_type, bytes_type, long_type, string_types
+from fractions import Fraction
 
 
 class HyObject(object):
@@ -229,6 +230,8 @@ class HyExpression(HyList):
         return "(%s)" % (" ".join([repr(x) for x in self]))
 
 _wrappers[HyExpression] = lambda e: HyExpression(wrap_value(x) for x in e)
+_wrappers[Fraction] = lambda e: HyExpression(
+    [HySymbol("fraction"), wrap_value(e.numerator), wrap_value(e.denominator)])
 
 
 class HySet(HyList):

eval doesn't use hy.models._wrappers
I came across this issue trying to narrow down a compiler error I was getting from a macro.
Why should the following piece of code throw an error?

```
=> (import numpy)


=> (= "." (get (name numpy) 0)))
False
=> (eval '(= "." (get (name numpy) 0)))
False
=> (eval `(= "." ~(get (name numpy) 0)))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Users/dg/anaconda3/lib/python3.5/site-packages/hy/importer.py", line 110, in hy_eval
    hytree.replace(foo)
  File "/Users/dg/anaconda3/lib/python3.5/site-packages/hy/models/list.py", line 31, in replace
    x.replace(other)
TypeError: replace() takes at least 2 arguments (1 given)
```

diff --git a/tests/compilers/test_ast.py b/tests/compilers/test_ast.py
index 2e880465..1bacdf08 100644
--- a/tests/compilers/test_ast.py
+++ b/tests/compilers/test_ast.py
@@ -7,9 +7,9 @@ from __future__ import unicode_literals
 from hy import HyString
 from hy.models import HyObject
 from hy.compiler import hy_compile
+from hy.importer import import_buffer_to_hst
 from hy.errors import HyCompileError, HyTypeError
 from hy.lex.exceptions import LexException
-from hy.lex import tokenize
 from hy._compat import PY3
 
 import ast
@@ -25,12 +25,12 @@ def _ast_spotcheck(arg, root, secondary):
 
 
 def can_compile(expr):
-    return hy_compile(tokenize(expr), "__main__")
+    return hy_compile(import_buffer_to_hst(expr), "__main__")
 
 
 def cant_compile(expr):
     try:
-        hy_compile(tokenize(expr), "__main__")
+        hy_compile(import_buffer_to_hst(expr), "__main__")
         assert False
     except HyTypeError as e:
         # Anything that can't be compiled should raise a user friendly
@@ -48,8 +48,10 @@ def cant_compile(expr):
 
 def test_ast_bad_type():
     "Make sure AST breakage can happen"
+    class C:
+        pass
     try:
-        hy_compile("foo", "__main__")
+        hy_compile(C(), "__main__")
         assert True is False
     except HyCompileError:
         pass
@@ -252,7 +254,7 @@ def test_ast_require():
 def test_ast_no_pointless_imports():
     def contains_import_from(code):
         return any([isinstance(node, ast.ImportFrom)
-                   for node in hy_compile(tokenize(code), "__main__").body])
+                   for node in can_compile(code).body])
     # `reduce` is a builtin in Python 2, but not Python 3.
     # The version of `map` that returns an iterator is a builtin in
     # Python 3, but not Python 2.
@@ -460,7 +462,7 @@ def test_ast_unicode_strings():
         hy_s.start_line = hy_s.end_line = 0
         hy_s.start_column = hy_s.end_column = 0
 
-        code = hy_compile([hy_s], "__main__")
+        code = hy_compile(hy_s, "__main__")
 
         # code == ast.Module(body=[ast.Expr(value=ast.Str(s=xxx))])
         return code.body[0].value.s
@@ -471,7 +473,7 @@ def test_ast_unicode_strings():
 
 
 def test_ast_unicode_vs_bytes():
-    def f(x): return hy_compile(tokenize(x), "__main__").body[0].value.s
+    def f(x): return can_compile(x).body[0].value.s
     assert f('"hello"') == u"hello"
     assert type(f('"hello"')) is (str if PY3 else unicode)  # noqa
     assert f('b"hello"') == (eval('b"hello"') if PY3 else "hello")
diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy
index 5b2421f5..b4f222d5 100644
--- a/tests/native_tests/language.hy
+++ b/tests/native_tests/language.hy
@@ -5,6 +5,7 @@
 (import [tests.resources [kwtest function-with-a-dash]]
         [os.path [exists isdir isfile]]
         [sys :as systest]
+        re
         [operator [or_]]
         [hy.errors [HyTypeError]]
         pytest)
@@ -1087,10 +1088,42 @@
 (defn test-eval-failure []
   "NATIVE: test eval failure modes"
   ; yo dawg
-  (try (eval '(eval)) (except [e HyTypeError]) (else (assert False)))
-  (try (eval '(eval "snafu")) (except [e HyTypeError]) (else (assert False)))
+  (try (eval '(eval)) (except [e TypeError]) (else (assert False)))
+  (defclass C)
+  (try (eval (C)) (except [e TypeError]) (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-eval-quasiquote []
+  ; https://github.com/hylang/hy/issues/1174
+
+  (for [x [
+      None False True
+      5 5.1
+      1/2
+      5j 5.1j 2+1j 1.2+3.4j
+      "" b""
+      "apple bloom" b"apple bloom" "⚘" b"\x00"
+      :mykeyword
+      [] #{} {}
+      [1 2 3] #{1 2 3} {"a" 1 "b" 2}]]
+    (assert (= (eval `(identity ~x)) x))
+    (assert (= (eval x) x)))
+
+  ; Tuples wrap to HyLists, not HyExpressions.
+  (assert (= (eval (,)) []))
+  (assert (= (eval (, 1 2 3)) [1 2 3]))
+
+  (assert (= (eval `(+ "a" ~(+ "b" "c"))) "abc"))
+
+  (setv l ["a" "b"])
+  (setv n 1)
+  (assert (= (eval `(get ~l ~n) "b")))
+
+  (setv d {"a" 1 "b" 2})
+  (setv k "b")
+  (assert (= (eval `(get ~d ~k)) 2)))
 
 
 (defn test-import-syntax []
@@ -1366,7 +1399,9 @@
     (assert (= (disassemble '(do (leaky) (leaky) (macros)))
                "Module(\n    body=[\n        Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n        Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n        Expr(value=Call(func=Name(id='macros'), args=[], keywords=[], starargs=None, kwargs=None))])")))
   (assert (= (disassemble '(do (leaky) (leaky) (macros)) True)
-             "leaky()\nleaky()\nmacros()")))
+             "leaky()\nleaky()\nmacros()"))
+  (assert (= (re.sub r"[L() ]" "" (disassemble `(+ ~(+ 1 1) 40) True))
+             "2+40")))
 
 
 (defn test-attribute-access []
diff --git a/tests/native_tests/native_macros.hy b/tests/native_tests/native_macros.hy
index 6089f323..6baa7a4f 100644
--- a/tests/native_tests/native_macros.hy
+++ b/tests/native_tests/native_macros.hy
@@ -84,6 +84,14 @@
   "NATIVE: test macro calling a plain function"
   (assert (= 3 (bar 1 2))))
 
+(defn test-optional-and-apply-in-macro []
+  ; https://github.com/hylang/hy/issues/1154
+  (defn f [&rest args]
+    (+ "f:" (repr args)))
+  (defmacro mac [&optional x]
+   `(apply f [~x]))
+  (assert (= (mac) "f:(None,)")))
+
 (defn test-midtree-yield []
   "NATIVE: test yielding with a returnable"
   (defn kruft [] (yield) (+ 1 1)))

pip install -e .
parse_log_pytest
pytest
pytest tox Pygments>=1.6 Sphinx sphinx_rtd_theme
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
appdirs==1.4.4
args==0.1.0
astor==0.8.1
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
Babel==2.11.0
certifi==2021.5.30
charset-normalizer==2.0.12
clint==0.5.1
distlib==0.3.9
docutils==0.18.1
filelock==3.4.1
-e git+https://github.com/hylang/hy.git@2e465dbf70624d2ab0923b878b68ed5a177da874#egg=hy
idna==3.10
imagesize==1.4.1
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
Jinja2==3.0.3
MarkupSafe==2.0.1
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
platformdirs==2.4.0
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
Pygments==2.14.0
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
pytz==2025.2
requests==2.27.1
rply==0.7.8
six==1.17.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinx-rtd-theme==2.0.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tox==3.28.0
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
urllib3==1.26.20
virtualenv==20.17.1
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: hy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - appdirs==1.4.4
      - args==0.1.0
      - astor==0.8.1
      - babel==2.11.0
      - charset-normalizer==2.0.12
      - clint==0.5.1
      - distlib==0.3.9
      - docutils==0.18.1
      - filelock==3.4.1
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - jinja2==3.0.3
      - markupsafe==2.0.1
      - platformdirs==2.4.0
      - pygments==2.14.0
      - pytz==2025.2
      - requests==2.27.1
      - rply==0.7.8
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinx-rtd-theme==2.0.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tox==3.28.0
      - urllib3==1.26.20
      - virtualenv==20.17.1
prefix: /opt/conda/envs/hy

tests/compilers/test_ast.py::test_ast_bad_type tests/compilers/test_ast.py::test_ast_bad_if tests/compilers/test_ast.py::test_ast_valid_if tests/compilers/test_ast.py::test_ast_valid_unary_op tests/compilers/test_ast.py::test_ast_invalid_unary_op tests/compilers/test_ast.py::test_ast_bad_while tests/compilers/test_ast.py::test_ast_good_do tests/compilers/test_ast.py::test_ast_good_raise tests/compilers/test_ast.py::test_ast_raise_from tests/compilers/test_ast.py::test_ast_bad_raise tests/compilers/test_ast.py::test_ast_good_try tests/compilers/test_ast.py::test_ast_bad_try tests/compilers/test_ast.py::test_ast_good_except tests/compilers/test_ast.py::test_ast_bad_except tests/compilers/test_ast.py::test_ast_good_assert tests/compilers/test_ast.py::test_ast_bad_assert tests/compilers/test_ast.py::test_ast_good_global tests/compilers/test_ast.py::test_ast_bad_global tests/compilers/test_ast.py::test_ast_good_nonlocal tests/compilers/test_ast.py::test_ast_bad_nonlocal tests/compilers/test_ast.py::test_ast_good_defclass tests/compilers/test_ast.py::test_ast_bad_defclass tests/compilers/test_ast.py::test_ast_good_lambda tests/compilers/test_ast.py::test_ast_bad_lambda tests/compilers/test_ast.py::test_ast_good_yield tests/compilers/test_ast.py::test_ast_bad_yield tests/compilers/test_ast.py::test_ast_good_import_from tests/compilers/test_ast.py::test_ast_require tests/compilers/test_ast.py::test_ast_no_pointless_imports tests/compilers/test_ast.py::test_ast_good_get tests/compilers/test_ast.py::test_ast_bad_get tests/compilers/test_ast.py::test_ast_good_cut tests/compilers/test_ast.py::test_ast_bad_cut tests/compilers/test_ast.py::test_ast_good_take tests/compilers/test_ast.py::test_ast_good_drop tests/compilers/test_ast.py::test_ast_good_assoc tests/compilers/test_ast.py::test_ast_bad_assoc tests/compilers/test_ast.py::test_ast_bad_with tests/compilers/test_ast.py::test_ast_valid_while tests/compilers/test_ast.py::test_ast_valid_for tests/compilers/test_ast.py::test_ast_invalid_for tests/compilers/test_ast.py::test_ast_expression_basics tests/compilers/test_ast.py::test_ast_anon_fns_basics tests/compilers/test_ast.py::test_ast_non_decoratable tests/compilers/test_ast.py::test_ast_lambda_lists tests/compilers/test_ast.py::test_ast_print tests/compilers/test_ast.py::test_ast_tuple tests/compilers/test_ast.py::test_argument_destructuring tests/compilers/test_ast.py::test_lambda_list_keywords_rest tests/compilers/test_ast.py::test_lambda_list_keywords_key tests/compilers/test_ast.py::test_lambda_list_keywords_kwargs tests/compilers/test_ast.py::test_lambda_list_keywords_kwonly tests/compilers/test_ast.py::test_lambda_list_keywords_mixed tests/compilers/test_ast.py::test_missing_keyword_argument_value tests/compilers/test_ast.py::test_ast_unicode_strings tests/compilers/test_ast.py::test_ast_unicode_vs_bytes tests/compilers/test_ast.py::test_compile_error tests/compilers/test_ast.py::test_for_compile_error tests/compilers/test_ast.py::test_attribute_access tests/compilers/test_ast.py::test_attribute_empty tests/compilers/test_ast.py::test_cons_correct tests/compilers/test_ast.py::test_invalid_list_comprehension tests/compilers/test_ast.py::test_bad_setv tests/compilers/test_ast.py::test_defn tests/compilers/test_ast.py::test_setv_builtins tests/native_tests/language.hy::test_sys_argv tests/native_tests/language.hy::test_hex tests/native_tests/language.hy::test_octal tests/native_tests/language.hy::test_binary tests/native_tests/language.hy::test_fractions tests/native_tests/language.hy::test_lists tests/native_tests/language.hy::test_dicts tests/native_tests/language.hy::test_sets tests/native_tests/language.hy::test_setv_get tests/native_tests/language.hy::test_setv_builtin tests/native_tests/language.hy::test_setv_pairs tests/native_tests/language.hy::test_setv_returns_none tests/native_tests/language.hy::test_store_errors tests/native_tests/language.hy::test_fn_corner_cases tests/native_tests/language.hy::test_alias_names_in_errors tests/native_tests/language.hy::test_for_loop tests/native_tests/language.hy::test_nasty_for_nesting tests/native_tests/language.hy::test_while_loop tests/native_tests/language.hy::test_branching tests/native_tests/language.hy::test_branching_with_do tests/native_tests/language.hy::test_branching_expr_count_with_do tests/native_tests/language.hy::test_cond tests/native_tests/language.hy::test_if tests/native_tests/language.hy::test_index tests/native_tests/language.hy::test_fn tests/native_tests/language.hy::test_imported_bits tests/native_tests/language.hy::test_kwargs tests/native_tests/language.hy::test_apply tests/native_tests/language.hy::test_apply_with_methods tests/native_tests/language.hy::test_dotted tests/native_tests/language.hy::test_do tests/native_tests/language.hy::test_exceptions tests/native_tests/language.hy::test_earmuffs tests/native_tests/language.hy::test_threading tests/native_tests/language.hy::test_tail_threading tests/native_tests/language.hy::test_threading_two tests/native_tests/language.hy::test_as_threading tests/native_tests/language.hy::test_assoc tests/native_tests/language.hy::test_multiassoc tests/native_tests/language.hy::test_pass tests/native_tests/language.hy::test_yield tests/native_tests/language.hy::test_yield_with_return tests/native_tests/language.hy::test_yield_in_try tests/native_tests/language.hy::test_first tests/native_tests/language.hy::test_cut tests/native_tests/language.hy::test_rest tests/native_tests/language.hy::test_importas tests/native_tests/language.hy::test_context tests/native_tests/language.hy::test_context_yield tests/native_tests/language.hy::test_with_return tests/native_tests/language.hy::test_for_doodle tests/native_tests/language.hy::test_for_else tests/native_tests/language.hy::test_list_comprehensions tests/native_tests/language.hy::test_set_comprehensions tests/native_tests/language.hy::test_dict_comprehensions tests/native_tests/language.hy::test_generator_expressions tests/native_tests/language.hy::test_defn_order tests/native_tests/language.hy::test_defn_return tests/native_tests/language.hy::test_defn_lambdakey tests/native_tests/language.hy::test_defn_do tests/native_tests/language.hy::test_defn_do_return tests/native_tests/language.hy::test_defn_dunder_name tests/native_tests/language.hy::test_mangles tests/native_tests/language.hy::test_fn_return tests/native_tests/language.hy::test_if_mangler tests/native_tests/language.hy::test_nested_mangles tests/native_tests/language.hy::test_symbol_utf_8 tests/native_tests/language.hy::test_symbol_dash tests/native_tests/language.hy::test_symbol_question_mark tests/native_tests/language.hy::test_and tests/native_tests/language.hy::test_and_#1151_do tests/native_tests/language.hy::test_and_#1151_for tests/native_tests/language.hy::test_and_#1151_del tests/native_tests/language.hy::test_or tests/native_tests/language.hy::test_or_#1151_do tests/native_tests/language.hy::test_or_#1151_for tests/native_tests/language.hy::test_or_#1151_del tests/native_tests/language.hy::test_xor tests/native_tests/language.hy::test_if_return_branching tests/native_tests/language.hy::test_keyword tests/native_tests/language.hy::test_keyword_clash tests/native_tests/language.hy::test_empty_keyword tests/native_tests/language.hy::test_nested_if tests/native_tests/language.hy::test_eval tests/native_tests/language.hy::test_eval_false tests/native_tests/language.hy::test_eval_globals tests/native_tests/language.hy::test_eval_failure tests/native_tests/language.hy::test_eval_quasiquote tests/native_tests/language.hy::test_import_syntax tests/native_tests/language.hy::test_lambda_keyword_lists tests/native_tests/language.hy::test_key_arguments tests/native_tests/language.hy::test_optional_arguments tests/native_tests/language.hy::test_undefined_name tests/native_tests/language.hy::test_if_in_if tests/native_tests/language.hy::test_try_except_return tests/native_tests/language.hy::test_try_else_return tests/native_tests/language.hy::test_require tests/native_tests/language.hy::test_require_native tests/native_tests/language.hy::test_encoding_nightmares tests/native_tests/language.hy::test_keyword_dict_access tests/native_tests/language.hy::test_break_breaking tests/native_tests/language.hy::test_continue_continuation tests/native_tests/language.hy::test_empty_list tests/native_tests/language.hy::test_string tests/native_tests/language.hy::test_del tests/native_tests/language.hy::test_macroexpand tests/native_tests/language.hy::test_macroexpand_1 tests/native_tests/language.hy::test_merge_with tests/native_tests/language.hy::test_calling_module_name tests/native_tests/language.hy::test_attribute_access tests/native_tests/language.hy::test_keyword_quoting tests/native_tests/language.hy::test_only_parse_lambda_list_in_defn tests/native_tests/language.hy::test_read tests/native_tests/language.hy::test_read_str tests/native_tests/language.hy::test_keyword_creation tests/native_tests/language.hy::test_name_conversion tests/native_tests/language.hy::test_keywords tests/native_tests/language.hy::test_keywords_and_macros tests/native_tests/language.hy::test_argument_destr tests/native_tests/native_macros.hy::test_rev_macro tests/native_tests/native_macros.hy::test_macro_kw tests/native_tests/native_macros.hy::test_fn_calling_macro tests/native_tests/native_macros.hy::test_optional_and_apply_in_macro tests/native_tests/native_macros.hy::test_midtree_yield tests/native_tests/native_macros.hy::test_midtree_yield_in_for tests/native_tests/native_macros.hy::test_midtree_yield_in_while tests/native_tests/native_macros.hy::test_multi_yield tests/native_tests/native_macros.hy::test_if_python2 tests/native_tests/native_macros.hy::test_gensym_in_macros tests/native_tests/native_macros.hy::test_with_gensym tests/native_tests/native_macros.hy::test_defmacro_g_bang tests/native_tests/native_macros.hy::test_defmacro_bang tests/native_tests/native_macros.hy::test_if_not tests/native_tests/native_macros.hy::test_lif tests/native_tests/native_macros.hy::test_lif_not tests/native_tests/native_macros.hy::test_yield_from tests/native_tests/native_macros.hy::test_yield_from_exception_handling tests/native_tests/native_macros.hy::test_defmain
tests/native_tests/language.hy::test_disassemble
hy/cmdline.py hy/models.py hy/compiler.py NEWS hy/core/language.hy docs/language/core.rst hy/importer.py docs/language/api.rst hy/macros.py
hy/cmdline.py hy/models.py hy/compiler.py NEWS hy/core/language.hy docs/language/core.rst hy/importer.py docs/language/api.rst hy/macros.py