From d580351b41a17fe008d1b8f8b73d6931fb604962 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Thu, 18 Jul 2013 15:00:24 +0300 Subject: [PATCH 1/8] initial macrodef documentation --- docs/language/api.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/language/api.rst b/docs/language/api.rst index c1235a7..f3adaf1 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -226,6 +226,21 @@ below: defmacro -------- +`defmacro` is used to define macros. + +The general format is `(defmacro [parameters] expr)`. + +Following example defines a macro that can be used to multiply all but the first +parameter given to it. + +.. codeblock:: clj + + => (defmacro multiply-some [&rest params] (quasiquote (* (unquote-splice (list (slice params 1)))))) + + => (multiply-some 0 2 3) + 6 + => (multiply-some 2 0 3) + 0 eval ---- From a17dcdbffbe7c7eb270ea669790b16faec3ce504 Mon Sep 17 00:00:00 2001 From: Nicolas Dandrimont Date: Fri, 19 Jul 2013 00:43:06 +0200 Subject: [PATCH 2/8] Make `with` return the last expression from its branch Thanks @rwtolbert for the bug report --- hy/compiler.py | 26 +++++++++++++++++++++----- tests/native_tests/language.hy | 7 +++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/hy/compiler.py b/hy/compiler.py index 70f329c..ba35791 100644 --- a/hy/compiler.py +++ b/hy/compiler.py @@ -1200,11 +1200,18 @@ class HyASTCompiler(object): thing = self._storeize(self.compile(args.pop(0))) body = self._compile_branch(expr) - body += body.expr_as_stmt() - if not body.stmts: - body += ast.Pass(lineno=expr.start_line, - col_offset=expr.start_column) + var = self.get_anon_var() + name = ast.Name(id=ast_str(var), arg=ast_str(var), + ctx=ast.Store(), + lineno=expr.start_line, + col_offset=expr.start_column) + + # Store the result of the body in a tempvar + body += ast.Assign(targets=[name], + value=body.force_expr, + lineno=expr.start_line, + col_offset=expr.start_column) the_with = ast.With(context_expr=ctx.force_expr, lineno=expr.start_line, @@ -1216,7 +1223,16 @@ class HyASTCompiler(object): the_with.items = [ast.withitem(context_expr=ctx.force_expr, optional_vars=thing)] - return ctx + the_with + ret = ctx + the_with + # And make our expression context our temp variable + expr_name = ast.Name(id=ast_str(var), arg=ast_str(var), + ctx=ast.Load(), + lineno=expr.start_line, + col_offset=expr.start_column) + + ret += Result(expr=expr_name, temp_variables=[expr_name, name]) + + return ret @builds(",") def compile_tuple(self, expr): diff --git a/tests/native_tests/language.hy b/tests/native_tests/language.hy index 00815b1..6dd2986 100644 --- a/tests/native_tests/language.hy +++ b/tests/native_tests/language.hy @@ -411,6 +411,13 @@ (with [(open "README.md" "r")] (do))) +(defn test-with-return [] + "NATIVE: test that with returns stuff" + (defn read-file [filename] + (with [fd (open filename "r")] (.read fd))) + (assert (!= 0 (len (read-file "README.md"))))) + + (defn test-for-doodle [] "NATIVE: test for-do" (do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0))))))))))) From 22d8a783300c2504c7bfa8d1eb011af0fdb07d63 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Fri, 19 Jul 2013 12:06:23 +0300 Subject: [PATCH 3/8] better macro example --- docs/language/api.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/language/api.rst b/docs/language/api.rst index f3adaf1..cf3cd1c 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -226,21 +226,23 @@ below: defmacro -------- -`defmacro` is used to define macros. +`defmacro` is used to define macros. The general format is +`(defmacro [parameters] expr)`. -The general format is `(defmacro [parameters] expr)`. - -Following example defines a macro that can be used to multiply all but the first -parameter given to it. +Following example defines a macro that can be used to swap order of elements in +code, allowing the user to write code in infix notation, where operator is in +between the operands. .. codeblock:: clj - => (defmacro multiply-some [&rest params] (quasiquote (* (unquote-splice (list (slice params 1)))))) + => (defmacro infix [code] + ... (quasiquote ( + ... (unquote (get code 1)) + ... (unquote (get code 0)) + ... (unquote (get code 2))))) - => (multiply-some 0 2 3) - 6 - => (multiply-some 2 0 3) - 0 + => (infix (1 + 1)) + 2 eval ---- From a786577a8b7a5e7bb2ef0d545ba7ad486c1b749d Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Fri, 19 Jul 2013 15:57:25 +0300 Subject: [PATCH 4/8] documentation for global --- docs/language/api.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/language/api.rst b/docs/language/api.rst index cf3cd1c..7443ed0 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -321,6 +321,25 @@ Example usages: global ------ +`global` can be used to mark a symbol as global. This allows the programmer to +assign a value to a global symbol. Reading a global symbol does not require the +`global` keyword, just the assigning does. + +Following example shows how global `a` is assigned a value in a function and later +on printed on another function. Without the `global` keyword, the second function +would thrown a `NameError`. + +.. code-block:: clj + + (defn set-a [value] + (global a) + (setv a value)) + + (defn print-a [] + (print a)) + + (set-a 5) + (print-a) if -- From ec76c6bee069f468d2c82589b40939967ca519b9 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Mon, 22 Jul 2013 23:36:59 +0300 Subject: [PATCH 5/8] documentation for require working on documenting macros --- docs/language/api.rst | 52 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/language/api.rst b/docs/language/api.rst index 7443ed0..420a05d 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -38,6 +38,14 @@ Hy features a number special forms that are used to help generate correct Python AST. The following are "special" forms, which may have behavior that's slightly unexpected in some situations. +-> +-- + + +->> +--- + + and --- @@ -129,6 +137,10 @@ the user enters `k`. (print "Try again"))) +cond +---- + + continue -------- @@ -223,6 +235,10 @@ below: Meow +defn / defun +------------ + + defmacro -------- @@ -233,7 +249,7 @@ Following example defines a macro that can be used to swap order of elements in code, allowing the user to write code in infix notation, where operator is in between the operands. -.. codeblock:: clj +.. code-block:: clj => (defmacro infix [code] ... (quasiquote ( @@ -256,6 +272,14 @@ eval-when-compile ----------------- +first / car +----------- + + +for +--- + + foreach ------- @@ -442,6 +466,10 @@ function is defined and passed to another function for filtering output. Dave +let +--- + + list-comp --------- @@ -533,6 +561,20 @@ the `print` form is used to output on screen. Example usage: require ------- +`require` is used to import macros from a given namespace. It takes at least one +parameter specifying the namespace which macros should be imported. Multiple +namesspaces can be imported with a single `require`. + +The following example will import macros from `namespace-1` and `namespace-2`: + +.. code-block:: clj + + (require namespace-1 namespace-2) + + +rest / cdr +---------- + slice ----- @@ -613,6 +655,14 @@ be executed. If no errors are raised the `else` block is executed. Regardless if an error was raised or not, the `finally` block is executed as last. +unless +------ + + +when +---- + + while ----- From c6410b70505b7233dd6b1a1857fa62b1cc70247e Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Mon, 22 Jul 2013 23:59:21 +0300 Subject: [PATCH 6/8] cond documentation --- docs/language/api.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/language/api.rst b/docs/language/api.rst index 420a05d..9acaeb1 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -140,6 +140,32 @@ the user enters `k`. cond ---- +`cond` macro can be used to build nested if-statements. + +The following example shows the relationship between the macro and the expanded +code: + +.. code-block:: clj + + (cond (condition-1 result-1) + (condition-2 result-2)) + + (if condition-1 result-1 + (if condition-2 result-2)) + +As shown below only the first matching result block is executed. + +.. code-block:: clj + + => (defn check-value [value] + ... (cond ((< value 5) (print "value is smaller than 5")) + ... ((= value 5) (print "value is equal to 5")) + ... ((> value 5) (print "value is greater than 5")) + ... (True (print "value is something that it should not be")))) + + => (check-value 6) + value is greater than 5 + continue -------- From 151ac69ce8329c650eb981459426b4825a975039 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Tue, 23 Jul 2013 00:36:34 +0300 Subject: [PATCH 7/8] working on documenting builtins --- docs/language/api.rst | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/docs/language/api.rst b/docs/language/api.rst index 9acaeb1..0e85e21 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -41,10 +41,30 @@ behavior that's slightly unexpected in some situations. -> -- +`->` or `threading macro` is used to avoid nesting of expressions. The threading +macro inserts each expression into the next expression’s first argument place. +The following code demonstrates this: + +.. code-block:: clj + + => (defn output [a b] (print a b)) + => (-> (+ 5 5) (output 5)) + 10 5 + ->> --- +`->>` or `threading tail macro` is similar to `threading macro` but instead of +inserting each expression into the next expression’s first argument place it +appends it as the last argument. The following code demonstrates this: + +.. code-block:: clj + + => (defn output [a b] (print a b)) + => (->> (+ 5 5) (output 5)) + 5 10 + and --- @@ -301,10 +321,29 @@ eval-when-compile first / car ----------- +`first` and `car` are macros for accessing the first element of a collection: + +.. code-block:: clj + + => (first (range 10)) + 0 + for --- +`for` macro is used to build nested `foreach` loops. The macro takes two +parameters, first being a vector specifying collections to iterate over and +variables to bind. The second parameter is a statement which is executed during +each loop: + +.. code-block:: clj + + (for [x iter y iter] stmt) + + (foreach [x iter] + (foreach [y iter] stmt)) + foreach ------- @@ -601,6 +640,14 @@ The following example will import macros from `namespace-1` and `namespace-2`: rest / cdr ---------- +`rest` and `cdr` are used to access every element in collection, except the +first one: + +.. code-block:: clj + + => (rest (range 10)) + [1, 2, 3, 4, 5, 6, 7, 8, 9] + slice ----- @@ -684,10 +731,29 @@ if an error was raised or not, the `finally` block is executed as last. unless ------ +`unless` macro is a shorthand for writing a if-statement that checks if the +given conditional is False. The following shows how the macro expands into code. + +.. code-block:: clj + + (unless conditional statement) + + (if conditional + None + (do statement)) when ---- +`when` is similar to `unless`, except it tests when the given conditional is +True. It is not possible to have an `else` block in `when` macro. The following +shows how the macro is expanded into code. + +.. code-block:: clj + + (when conditional statement) + + (if conditional (do statement)) while ----- From 6665a2b4902417b790b9ce095091a437d5889155 Mon Sep 17 00:00:00 2001 From: Tuukka Turto Date: Tue, 23 Jul 2013 06:39:29 +0300 Subject: [PATCH 8/8] clarified rest / cdr, cleaned up require --- docs/language/api.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/language/api.rst b/docs/language/api.rst index 0e85e21..b279ab3 100644 --- a/docs/language/api.rst +++ b/docs/language/api.rst @@ -626,22 +626,22 @@ the `print` form is used to output on screen. Example usage: require ------- -`require` is used to import macros from a given namespace. It takes at least one -parameter specifying the namespace which macros should be imported. Multiple -namesspaces can be imported with a single `require`. +`require` is used to import macros from a given module. It takes at least one +parameter specifying the module which macros should be imported. Multiple +modules can be imported with a single `require`. -The following example will import macros from `namespace-1` and `namespace-2`: +The following example will import macros from `module-1` and `module-2`: .. code-block:: clj - (require namespace-1 namespace-2) + (require module-1 module-2) rest / cdr ---------- -`rest` and `cdr` are used to access every element in collection, except the -first one: +`rest` and `cdr` return the collection passed as an argument without the first +element: .. code-block:: clj