1
Fork 0
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:
Phil 2011-05-07 16:15:11 -05:00 committed by Ian Price
parent faa16f9989
commit f4c44a3ba7
9 changed files with 130 additions and 46 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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")

View file

@ -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)"))

View file

@ -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)

View file

@ -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 "+" #\+)