mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-07-02 07:40:30 +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
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue