Skip to content

Commit

Permalink
allow inner functions signatures to depend on static parameters
Browse files Browse the repository at this point in the history
there is logic present to also handle all locals,
but this causes some broken toplevel lowering to fail
(notably, some gensym locals are getting pulled into global scope
and some toplevel scopes are incorrectly identified as local scope)

fix #15068
  • Loading branch information
vtjnash committed Jul 18, 2016
1 parent 547375b commit 69b5f3a
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 47 deletions.
8 changes: 4 additions & 4 deletions src/jlfrontend.scm
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
`(incomplete ,msg)
e))
(begin
;;(newline)
;;(display "unexpected error: ")
;;(prn e)
;;(print-stack-trace (stacktrace))
(newline)
(display "unexpected error: ")
(prn e)
(print-stack-trace (stacktrace))
'(error "malformed expression"))))
thk))

Expand Down
122 changes: 81 additions & 41 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -2475,32 +2475,55 @@ end
f(x) = yt(x)
|#

;; template for generating a closure type with parameters
(define (type-for-closure-parameterized name P fields types super)
(let ((n (length P)))
`(thunk
(define (type-for-closure-parameterized name P names fields types super)
(let ((n (length P)))
`((thunk
(lambda ()
((,@(map (lambda (p) `(,p Any 18)) P))
() 0 ())
(() () 0 ())
(body (global ,name) (const ,name)
,@(map (lambda (p) `(= ,p (call (core TypeVar) ',p (core Any) false))) P)
,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any) false))) P names)
(composite_type ,name (call (core svec) ,@P)
(call (core svec) ,@(map (lambda (v) `',v) fields))
,super
(call (core svec) ,@types) false ,(length fields))
(return (null)))))))
(return (null))))))))

;; ... and without parameters
(define (type-for-closure name fields super)
`(thunk (lambda ()
`((thunk (lambda ()
(() () 0 ())
(body (global ,name) (const ,name)
(composite_type ,name (call (core svec))
(call (core svec) ,@(map (lambda (v) `',v) fields))
,super
(call (core svec) ,@(map (lambda (v) 'Any) fields))
false ,(length fields))
(return (null))))))
(return (null)))))))


;; better versions of above, but they gets handled wrong in many places
;; need to fix that in order to handle #265 fully (and use the definitions)

;; template for generating a closure type with parameters
;(define (type-for-closure-parameterized name P names fields types super)
; (let ((n (length P)))
; `((global ,name)
; (const ,name)
; ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any) false))) P names)
; (composite_type ,name (call (core svec) ,@P)
; (call (core svec) ,@(map (lambda (v) `',v) fields))
; ,super
; (call (core svec) ,@types) false ,(length fields)))))

;; ... and without parameters
;(define (type-for-closure name fields super)
; `((global ,name)
; (const ,name)
; (composite_type ,name (call (core svec))
; (call (core svec) ,@(map (lambda (v) `',v) fields))
; ,super
; (call (core svec) ,@(map (lambda (v) 'Any) fields))
; false ,(length fields))))


(define (vinfo:not-capt vi)
(list (car vi) (cadr vi) (logand (caddr vi) (lognot 5))))
Expand Down Expand Up @@ -2770,9 +2793,10 @@ f(x) = yt(x)
(lam2 (if short #f (cadddr e)))
(vis (if short '(() () ()) (lam:vinfo lam2)))
(cvs (map car (cadr vis)))
(local? (and lam (symbol? name)
(or (assq name (car (lam:vinfo lam)))
(assq name (cadr (lam:vinfo lam))))))
(local? (lambda (s) (and (symbol? s)
(or (assq s (car (lam:vinfo lam)))
(assq s (cadr (lam:vinfo lam)))))))
(local (and lam (local? name)))
(sig (and (not short) (caddr e)))
(sp-inits (if (or short (not (eq? (car sig) 'block)))
'()
Expand All @@ -2781,14 +2805,14 @@ f(x) = yt(x)
(sig (and sig (if (eq? (car sig) 'block)
(last sig)
sig))))
(if local?
(if local
(begin (if (memq name (lam:args lam))
(error (string "cannot add method to function argument " name)))
(if (eqv? (string.char (string name) 0) #\@)
(error "macro definition not allowed inside a local scope"))))
(if lam2
(lambda-optimize-vars! lam2))
(if (not local?) ;; not a local function; will not be closure converted to a new type
(if (not local) ;; not a local function; will not be closure converted to a new type
(cond (short e)
((null? cvs)
`(block
Expand Down Expand Up @@ -2837,18 +2861,51 @@ f(x) = yt(x)
alldefs))))
(capt-sp (simple-sort (intersect cvs sps)))
(capt-vars (diff cvs capt-sp))
(find-locals (lambda (methdef)
(expr-find-all
(lambda (s) (and (not (eq? name s))
(not (memq s capt-sp))
(or ;(local? s) ; TODO: make this work for local variables too
(memq s (lam:sp lam)))))
(caddr methdef)
identity)))
(sig-locals (simple-sort
(delete-duplicates ;; locals used in sig from all definitions
(apply append ;; will convert these into sparams for dispatch
(if lam2 (find-locals e) '())
(map find-locals alldefs)))))
(capt-sp (append capt-sp sig-locals)) ; sparams for the closure method declaration
(method-sp (map (lambda (s) (make-ssavalue)) capt-sp))
(typedef ;; expression to define the type
(let* ((fieldtypes (map (lambda (v)
(if (is-var-boxed? v lam)
'(core Box)
(gensy)))
capt-vars))
(para (append capt-sp
(filter (lambda (v) (symbol? v)) fieldtypes))))
(make-ssavalue)))
capt-vars))
(para (append method-sp
(filter (lambda (v) (ssavalue? v)) fieldtypes)))
(fieldnames (append capt-sp (filter (lambda (v) (not (is-var-boxed? v lam))) capt-vars))))
(if (null? para)
(type-for-closure tname capt-vars '(core Function))
(type-for-closure-parameterized tname para capt-vars fieldtypes '(core Function)))))
(type-for-closure-parameterized tname para fieldnames capt-vars fieldtypes '(core Function)))))
(mk-method ;; expression to make the method
(if short '()
(let* ((iskw ;; TODO jb/functions need more robust version of this
(contains (lambda (x) (eq? x 'kwftype)) sig))
(renamemap (map cons capt-sp method-sp))
(arg-defs (replace-vars
(fix-function-arg-type sig tname iskw namemap method-sp)
renamemap)))
(append (map (lambda (gs tvar)
(make-assignment gs `(call (core TypeVar) ',tvar (core Any) true)))
method-sp capt-sp)
`((method #f ,(cl-convert arg-defs fname lam namemap toplevel interp)
,(convert-lambda lam2
(if iskw
(caddr (lam:args lam2))
(car (lam:args lam2)))
#f capt-sp)
,(last e)))))))
(mk-closure ;; expression to make the closure
(let* ((var-exprs (map (lambda (v)
(let ((cv (assq v (cadr (lam:vinfo lam)))))
Expand All @@ -2868,31 +2925,14 @@ f(x) = yt(x)
`(new ,(if (null? P)
tname
`(call (core apply_type) ,tname ,@P))
,@var-exprs)))
(iskw ;; TODO jb/functions need more robust version of this
(contains (lambda (x) (eq? x 'kwftype)) sig)))
,@var-exprs))))
`(toplevel-butlast
,@(if exists
'()
(list
(begin (and name (put! namemap name tname))
typedef)))
typedef))
,@sp-inits
,@(if short '()
(map (lambda (gs tvar)
(make-assignment gs `(call (core TypeVar) ',tvar (core Any) true)))
method-sp capt-sp))
,@(if short '()
`((method #f
,(cl-convert
(fix-function-arg-type sig tname iskw namemap method-sp)
fname lam namemap toplevel interp)
,(convert-lambda lam2
(if iskw
(caddr (lam:args lam2))
(car (lam:args lam2)))
#f capt-sp)
,(last e))))
,@mk-method
,(if exists
'(null)
(convert-assignment name mk-closure fname lam interp)))))))
Expand Down
3 changes: 1 addition & 2 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,8 @@ JL_DLLEXPORT jl_value_t *jl_module_names(jl_module_t *m, int all, int imported)
for(i=1; i < m->bindings.size; i+=2) {
if (table[i] != HT_NOTFOUND) {
jl_binding_t *b = (jl_binding_t*)table[i];
int hidden = jl_symbol_name(b->name)[0]=='#';
if ((b->exportp || ((imported || b->owner == m) && (all || m == jl_main_module))) &&
!b->deprecated && !hidden) {
!b->deprecated) {
jl_array_grow_end(a, 1);
//XXX: change to jl_arrayset if array storage allocation for Array{Symbols,1} changes:
jl_array_ptr_set(a, jl_array_dim0(a)-1, (jl_value_t*)b->name);
Expand Down
19 changes: 19 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4471,3 +4471,22 @@ function captsp{T, S}(x::T, y::S)
return subf(Int(1)), subf(UInt(1))
end
@test captsp(1, 2.0) == (Int, Float64)

# issue #15068
function sp_innersig{T}(x::T)
subf(x2::T) = (x, x2, :a)
subf(x2) = (x, x2, :b)
return (subf(one(T)), subf(unsigned(one(T))))
end
@test sp_innersig(2) == ((2, 1, :a), (2, UInt(1), :b))

# TODO: broken - also with local variables
#function local_innersig{T}(x::T)
# V = typeof(x)
# U = unsigned(T)
# subf(x2::T, x3::Complex{V}) = (x, x2, x3)
# subf(x2::U) = (x, x2)
# return (subf(one(T), x * im), subf(unsigned(one(T))))
#end
#@test local_innersig(Int32(2)) == ((Int32(2), Int32(1), Int32(2)im), (Int32(2), UInt32(1)))
#@test local_innersig(Int64(3)) == ((Int64(3), Int64(1), Int64(3)im), (Int64(3), UInt64(1)))

0 comments on commit 69b5f3a

Please sign in to comment.