mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-02 21:10:27 +02:00
Add some documentation. Function calls now properly handle multiple
values resulting from a function call as the last argument. doc/ref/api-languages.texi: Add a small blurb about Lua. module/language/lua/compile-tree-il.scm: Function calls now properly handle multiple values resulting from a function call as the last argument.
This commit is contained in:
parent
faa16f9989
commit
f4c44a3ba7
9 changed files with 130 additions and 46 deletions
|
@ -9,7 +9,7 @@
|
|||
|
||||
In addition to Scheme, a user may write a Guile program in an increasing
|
||||
number of other languages. Currently supported languages include Emacs
|
||||
Lisp and ECMAScript.
|
||||
Lisp, ECMAScript, and Lua.
|
||||
|
||||
Guile is still fundamentally a Scheme, but it tries to support a wide
|
||||
variety of language building-blocks, so that other languages can be
|
||||
|
@ -24,6 +24,7 @@ Virtual Machine}.)
|
|||
* Using Other Languages:: How to use other languages.
|
||||
* Emacs Lisp:: The dialect of Lisp used in Emacs.
|
||||
* ECMAScript:: As seen on television.
|
||||
* Lua:: A flexible scripting language.
|
||||
@end menu
|
||||
|
||||
|
||||
|
@ -270,6 +271,29 @@ perhaps by some more responsible hacker.
|
|||
In the meantime, the charitable user might investigate such invocations
|
||||
as @code{,L ecmascript} and @code{cat test-suite/tests/ecmascript.test}.
|
||||
|
||||
@node Lua
|
||||
@subsection Lua
|
||||
|
||||
@url{http://www.lua.org,Lua}
|
||||
is a powerful scripting language similar in many ways to Scheme.
|
||||
Support for Lua 5.1 was added to Guile to make Guile a more attractive
|
||||
option for extending programs, and to make it possible for projects
|
||||
already using Lua to switch to Guile without giving up support for Lua.
|
||||
|
||||
This section of the manual documents Guile's implementation of Lua. For
|
||||
documentation of the Lua language, please see
|
||||
@url{http://www.lua.org/docs.html,Lua's official documentation}.
|
||||
|
||||
Guile's implementation of Lua is intended to behave exactly like the
|
||||
reference implementation of Lua 5.1, but problems are to be expected. If
|
||||
your Lua programs act strangely, it may very well be a problem with
|
||||
Guile's Lua.
|
||||
|
||||
Notes:
|
||||
|
||||
collectgarbage is not fully supported. Attempting to use collectgarbage
|
||||
with an argument other than ``collect'' will result in a warning being
|
||||
printed.
|
||||
|
||||
@c Local Variables:
|
||||
@c TeX-master: "guile.texi"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
(define-module (language lua compile-tree-il)
|
||||
#:use-module (language tree-il)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-39)
|
||||
#:use-module ((system base syntax) #:select (record-case))
|
||||
#:use-module (rnrs control)
|
||||
|
@ -35,20 +36,45 @@
|
|||
|
||||
|
||||
(define (ref-runtime src name)
|
||||
"Shorthand for referring to a variable in the (language lua runtime) module"
|
||||
(make-module-ref src *runtime-name* name #t))
|
||||
|
||||
(define (make-runtime-application src name arguments)
|
||||
"Apply a function in the (language lua runtime) module"
|
||||
"Shorthand for creating an application of a function in the (language lua runtime) module"
|
||||
(make-application src (ref-runtime src name) arguments))
|
||||
|
||||
(define (make-table-ref src table index)
|
||||
"Shorthand for calling the index function in (language lua runtime)"
|
||||
(make-runtime-application src 'index
|
||||
(list table (if (symbol? index) (make-const src (symbol->string index)) index))))
|
||||
|
||||
(define (make-table-set! src table index exp)
|
||||
"Shorthand for calling the new-index! function in (language lua runtime)"
|
||||
(make-runtime-application src 'new-index!
|
||||
(list table (if (symbol? index) (make-const src (symbol->string index)) index) exp)))
|
||||
|
||||
;; Calling conventions
|
||||
(define* (make-plain-lambda-case src args gensyms body #:optional alternate)
|
||||
(make-lambda-case src args #f #f #f '() (or gensyms args) body alternate))
|
||||
|
||||
(define* (make-plain-lambda src args gensyms body #:optional alternate)
|
||||
(make-lambda src '()
|
||||
(make-plain-lambda-case src args gensyms body alternate)))
|
||||
|
||||
(define (make-arg-ignoring-lambda src body)
|
||||
(make-lambda src '()
|
||||
(make-lambda-case src '() #f '_ #f '() (list (gensym "_"))
|
||||
body #f)))
|
||||
|
||||
(define (make-catch-all-lambda src body rest-gensym)
|
||||
(make-lambda src '()
|
||||
(make-lambda-case src '() #f 'rest #f '() (list rest-gensym)
|
||||
body #f)))
|
||||
|
||||
(define (make-argless-lambda src body)
|
||||
(make-plain-lambda src '() #f body))
|
||||
|
||||
|
||||
;; FIXME: use prompt and abort rather than catch and throw
|
||||
(define (apply-named-lua-function src name get-body)
|
||||
(let* ((name (gensym (string-append " " name)))
|
||||
|
@ -81,24 +107,15 @@
|
|||
(make-application src (make-lexical-ref src loop loop) '())))
|
||||
(make-void src)))))
|
||||
|
||||
;; calling conventions
|
||||
(define* (make-plain-lambda-case src args gensyms body #:optional alternate)
|
||||
(make-lambda-case src args #f #f #f '() (or gensyms args) body alternate))
|
||||
(define (could-result-in-multiple-values? x)
|
||||
(if (not (null? x))
|
||||
(let ((last-expr (last x)))
|
||||
(or (ast-function-call? last-expr) (ast-variable-arguments? last-expr)))
|
||||
#f))
|
||||
|
||||
(define* (make-plain-lambda src args gensyms body #:optional alternate)
|
||||
(make-lambda src '()
|
||||
(make-plain-lambda-case src args gensyms body alternate)))
|
||||
|
||||
(define (make-arg-ignoring-lambda src body)
|
||||
(make-lambda src '()
|
||||
(make-lambda-case src '() #f '_ #f '() (list (gensym "_"))
|
||||
body #f)))
|
||||
|
||||
(define (make-argless-lambda src body)
|
||||
(make-plain-lambda src '() #f body))
|
||||
|
||||
(define (adjust-to-single-value src exp)
|
||||
"adjust an expression so that it only returns one result; the rest are
|
||||
;; TODO REMOVE
|
||||
#;(define (adjust-to-single-value src exp)
|
||||
"Adjust an expression so that it only returns one result; the rest are
|
||||
dropped silently"
|
||||
;; Rely on the truncating behavior of returning multiple values to a
|
||||
;; singly-valued continuation.
|
||||
|
@ -153,12 +170,40 @@ dropped silently"
|
|||
#f))))
|
||||
|
||||
((ast-function-call src operator operands)
|
||||
#| (let* ((proc (compile operator))
|
||||
(args (make-application src (make-primitive-ref src 'list) (map-compile operands)))
|
||||
(app-args (make-application src (make-primitive-ref src 'list) (list proc args)))
|
||||
(app (make-application src (make-primitive-ref src 'apply) (list (make-primitive-ref src 'apply) app-args)))) |#
|
||||
(let* ((proc (compile operator))
|
||||
(app (make-application src proc (map-compile operands))))
|
||||
;; will be #t if the the last expression in the list is a
|
||||
;; function call or variable arguments, which means we need
|
||||
;; to account for #<values>
|
||||
(need-to-apply-multiple-values? (could-result-in-multiple-values? operands))
|
||||
(args (map-compile operands)))
|
||||
(define app
|
||||
(if need-to-apply-multiple-values?
|
||||
;; Get the last function's (the one that could result in
|
||||
;; multiple values) return values using call-with-values
|
||||
;; and a function that takes variable arguments. Then
|
||||
;; append those variable arguments to the rest of the
|
||||
;; expression, and apply the first function to it)
|
||||
(make-application src
|
||||
(make-primitive-ref src 'call-with-values)
|
||||
(list
|
||||
(make-argless-lambda src (make-sequence src (last-pair args)))
|
||||
(let ((rest-gensym (gensym "rest")))
|
||||
(make-catch-all-lambda src
|
||||
(make-application src (make-primitive-ref src 'apply)
|
||||
(list
|
||||
proc
|
||||
(make-application src
|
||||
(make-module-ref src '(srfi srfi-1) 'append! #t)
|
||||
(list
|
||||
(make-application src (make-primitive-ref src 'list) (drop-right args 1))
|
||||
(make-lexical-ref src 'rest rest-gensym)))))
|
||||
rest-gensym))))
|
||||
|
||||
(make-application src proc args)))
|
||||
|
||||
;; If this is function is a global variable, prepend a call to
|
||||
;; check-global-function to make sure it's defined before
|
||||
;; applying it
|
||||
(if (ast-global-ref? operator)
|
||||
(make-sequence
|
||||
src (list
|
||||
|
|
|
@ -5,17 +5,32 @@ This is an org-mode todo list of stuff that needs to be done for Guile Lua.
|
|||
CLOSED: [2011-04-19 Tue 19:36]
|
||||
** DONE Standard library functions: math.modf, math.fmod
|
||||
CLOSED: [2011-04-21 Thu 15:43]
|
||||
** TODO Variable arguments and multiple returns
|
||||
** TODO Assignment cannot be naive left-to-right
|
||||
a,b = b,a should work correctly
|
||||
** STARTED Multiple values
|
||||
What's the deal? In Lua, the rightmost expression in a
|
||||
comma-delimited list (such as in a function application, or the
|
||||
right-hand side of an assignment) may result in multiple values.
|
||||
|
||||
** TODO Variable arguments
|
||||
|
||||
** TODO Function environments (getfenv and setfenv)
|
||||
** TODO Use prompt and abort instead of throw and catch
|
||||
** TODO Standard library function: module
|
||||
** TODO Standard library function: table.sort
|
||||
** TODO Get the official Lua 5.1 test suite running
|
||||
** TODO Lua working at the REPL
|
||||
** TODO Document some stuff
|
||||
|
||||
* Eh
|
||||
** TODO Standard library function: math.frexp
|
||||
Pending some additions to Guile's numeric tower.
|
||||
** TODO Use module binders
|
||||
** TODO Better testing of standard library modules io, os
|
||||
** TODO Function environments (getfenv and setfenv)
|
||||
** TODO compile-tree-il.scm should be rewritten
|
||||
Right now it's a jungle of tree-il constructors. There's a lot of
|
||||
boilerplate code that could be made much nicer using macros and
|
||||
parse-tree-il.
|
||||
|
||||
* Differences
|
||||
Here are some difference in Guile Lua's behavior that should not cause
|
||||
|
|
|
@ -351,7 +351,7 @@
|
|||
(enforce-next! #\))
|
||||
;; finished
|
||||
save))
|
||||
(else (syntax-error (get-source-info) "unexpected symbol ~a" token))))
|
||||
(else (syntax-error (get-source-info) "unexpected token ~a" token))))
|
||||
|
||||
;; index -> '[' expression ']'
|
||||
(define (index)
|
||||
|
@ -598,7 +598,6 @@
|
|||
|
||||
;; FIXME: does a left-to-right assignment, so x, y = y, x probably
|
||||
;; doesn't work. Also does not appear to handle the x, y = foo() case.
|
||||
;;
|
||||
(define (parse-assignment src left right)
|
||||
;; and then parses it, branching to handle overflows on either side if necessary
|
||||
(make-ast-sequence
|
||||
|
|
|
@ -332,10 +332,7 @@
|
|||
(runtime-error "~a" (if (null? opts) "assertion failed" (car opts)))))
|
||||
|
||||
;; NOTE: collectgarbage cannot be fully implemented because it expects
|
||||
;; an incremental garbage collector that matches lua's interface; libgc
|
||||
;; can be incremental but i don't think we can turn that on from guile
|
||||
;; currently, and even if we could i'm not sure that libgc exposes what
|
||||
;; lua wants
|
||||
;; an incremental garbage collector that matches lua's interface
|
||||
(define-global collectgarbage
|
||||
(lambda* (opt #:optional (arg #nil))
|
||||
(define (ignore) (runtime-warning "collectgarbage cannot respect command ~a" opt))
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
(define-module (test-lua)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (language tree-il)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-8)
|
||||
#:use-module (system base compile)
|
||||
#:use-module (test-suite lib)
|
||||
|
||||
|
@ -102,7 +99,7 @@
|
|||
(test "print \"hello world\"; return true")
|
||||
|
||||
;; variable arguments
|
||||
#;(test "function test(...) print(...) end test(1,2)")
|
||||
(test "function test(...) print(...) end test(1,2)")
|
||||
|
||||
;; numeric for loop
|
||||
(test "for x = 1,2,1 do print(true) end return true")
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
(define-module (test-lua)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (language tree-il)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-8)
|
||||
#:use-module (system base compile)
|
||||
#:use-module (test-suite lib)
|
||||
|
||||
|
@ -41,9 +38,22 @@
|
|||
((_ string)
|
||||
(test string #t)))))
|
||||
|
||||
#|
|
||||
;; make sure logical expressions don't evaluate expressions twice
|
||||
;;; y will equal 2 in case of extra eval
|
||||
(test "y = 0 function tmp() y = y + 1 return true end assert(tmp() or tmp()) return y == 1")
|
||||
;;; y will equal 4 in case of extra eval
|
||||
(test "y = 0 function void(x) end function tmp() y = y + 2 return false end; function tmp2() y = y + 1 return true end; void(tmp() and tmp2()) return y == 2")
|
||||
|#
|
||||
1
|
||||
))
|
||||
|
||||
|
||||
(define (from-string string)
|
||||
(compile ((make-parser (open-input-string string)))
|
||||
#:from 'lua
|
||||
#:to 'value))
|
||||
|
||||
;(format #t "~a\n" (from-string "function tmp() return 4,5 end print(1,2,3,tmp())"))
|
||||
|
||||
(format #t "~a\n" (from-string "function tmp(...) print(1,2,3,...) end tmp(4,5)"))
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
(define-module (test-lua)
|
||||
#:use-module (ice-9 format)
|
||||
#:use-module (language tree-il)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (srfi srfi-8)
|
||||
#:use-module (system base compile)
|
||||
#:use-module (test-suite lib)
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
;;;; modify it under the terms of the GNU Lesser General Public
|
||||
;;;; License as published by the Free Software Foundation; either
|
||||
;;;; version 3 of the License, or (at your option) any later version.
|
||||
;;;;
|
||||
;;;;
|
||||
;;;; This library is distributed in the hope that it will be useful,
|
||||
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
;;;; Lesser General Public License for more details.
|
||||
;;;;
|
||||
;;;;
|
||||
;;;; You should have received a copy of the GNU Lesser General Public
|
||||
;;;; License along with this library; if not, write to the Free Software
|
||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
@ -29,7 +29,7 @@
|
|||
(call-with-input-string string make-lexer))
|
||||
(lambda (get-source-info lex)
|
||||
(lex))))
|
||||
|
||||
|
||||
(let-syntax
|
||||
((test
|
||||
(syntax-rules (eof)
|
||||
|
@ -62,7 +62,7 @@ comment]]"))
|
|||
(test "name" 'name)
|
||||
(test "return" #:return)
|
||||
(test ".." #:concat)
|
||||
(test "..." #:dots)
|
||||
(test "..." #:vararg)
|
||||
(test ";" #\;)
|
||||
(test "-" #\-)
|
||||
(test "+" #\+)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue