From 5808ceb5845d4fffa3f7cb9eca2e370c339a862f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 30 Jan 2017 14:39:48 -0500 Subject: [PATCH 1/2] remove 0.5 syntax deprecation warnings --- base/show.jl | 7 ++-- src/julia-parser.scm | 76 ++++++++++++-------------------------------- src/julia-syntax.scm | 60 ++++++++-------------------------- test/core.jl | 14 ++++++++ test/parse.jl | 5 +-- 5 files changed, 51 insertions(+), 111 deletions(-) diff --git a/base/show.jl b/base/show.jl index d6283f5f7db48..f1bbea2d2c6b6 100644 --- a/base/show.jl +++ b/base/show.jl @@ -800,16 +800,13 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) show_call(io, head, ex.args[1], funcargslike, indent) # comprehensions - elseif (head === :typed_comprehension || head === :typed_dict_comprehension) && length(args) == 2 - isdict = (head === :typed_dict_comprehension) - isdict && print(io, '(') + elseif head === :typed_comprehension && length(args) == 2 show_unquoted(io, args[1], indent) - isdict && print(io, ')') print(io, '[') show_generator(io, args[2], indent) print(io, ']') - elseif (head === :comprehension || head === :dict_comprehension) && length(args) == 1 + elseif head === :comprehension && length(args) == 1 print(io, '[') show_generator(io, args[1], indent) print(io, ']') diff --git a/src/julia-parser.scm b/src/julia-parser.scm index a6cae89d91927..c280447672098 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -123,9 +123,6 @@ (define reserved-word? (Set reserved-words)) -(define (dict-literal? l) - (and (length= l 3) (eq? (car l) '=>))) - ;; Parser state variables ; disable range colon for parsing ternary conditional operator @@ -896,6 +893,8 @@ (define (invalid-identifier-name? ex) ;; TODO: remove this hack when we remove the special Dict syntax + ;; TODO: Dict syntax removed, but need to decide whether to change the parsing + ;; of `a=>b` to use `call`. (or (and (not (eq? ex '=>)) (syntactic-op? ex)) (eq? ex '....))) @@ -999,11 +998,6 @@ (parse-where-chain s decl-sig) decl-sig))) -(define (deprecated-dict-replacement ex) - (if (dict-literal? ex) - (string "Dict{" (deparse (cadr ex)) #\, (deparse (caddr ex)) "}") - "Dict")) - (define (disallowed-space ex t) (error (string "space before \"" t "\" not allowed in \"" (deparse ex) " " (deparse t) "\""))) @@ -1054,7 +1048,7 @@ ;; ref is syntax, so we can distinguish ;; a[i] = x from ;; ref(a,i) = x - (let ((al (with-end-symbol (parse-cat s #\] (dict-literal? ex))))) + (let ((al (with-end-symbol (parse-cat s #\])))) (if (null? al) (loop (list 'ref ex)) (case (car al) @@ -1064,11 +1058,6 @@ (loop (list* 'typed_vcat ex (cdr al)))) ((comprehension) (loop (list* 'typed_comprehension ex (cdr al)))) - ((dict_comprehension) - (syntax-deprecation - s (string #\( (deparse ex) #\) "[a=>b for (a,b) in c]") - (string (deprecated-dict-replacement ex) "(a=>b for (a,b) in c)")) - (loop (list* 'typed_dict_comprehension ex (cdr al)))) (else (error "unknown parse-cat result (internal error)")))))) ((|.|) (if (ts:space? s) (disallowed-space ex t)) @@ -1177,8 +1166,7 @@ ((if) (if (newline? (peek-token s)) - (syntax-deprecation s "if with line break before condition" "") - #;(error (string "missing condition in \"if\" at " current-filename + (error (string "missing condition in \"if\" at " current-filename ":" (- (input-port-line (ts:port s)) 1)))) (let* ((test (parse-cond s)) (then (if (memq (require-token s) '(else elseif)) @@ -1462,8 +1450,7 @@ ;; as above, but allows both "i=r" and "i in r" (define (parse-iteration-spec s) - (let* ((paren? (eqv? (require-token s) #\()) - (lhs (parse-pipes s)) + (let* ((lhs (parse-pipes s)) (t (peek-token s))) (cond ((memq t '(= in ∈)) (take-token s) @@ -1476,13 +1463,6 @@ `(= ,lhs ,rhs))) ((and (eq? lhs ':) (closing-token? t)) ':) - ((and paren? (length= lhs 4) (eq? (car lhs) 'call) - (memq (cadr lhs) '(in ∈))) - (syntax-deprecation s "for (...)" "for ...") - `(= ,@(cddr lhs))) - ((and paren? (length= lhs 3) (eq? (car lhs) '=)) - (syntax-deprecation s "for (...)" "for ...") - lhs) (else (error "invalid iteration specification"))))) (define (parse-comma-separated-iters s) @@ -1602,12 +1582,6 @@ (take-token s)) `(comprehension ,gen)))) -(define (parse-dict-comprehension s first closer) - (let ((c (parse-comprehension s first closer))) - (if (dict-literal? (cadr (cadr c))) - `(dict_comprehension ,@(cdr c)) - (error "invalid dict comprehension")))) - (define (parse-matrix s first closer gotnewline) (define (fix head v) (cons head (reverse v))) (define (update-outer v outer) @@ -1653,32 +1627,26 @@ (loop (peek-token s))) t))) -(define (parse-cat s closer . isdict) +(define (parse-cat s closer) (with-normal-ops (with-inside-vec (if (eqv? (require-token s) closer) (begin (take-token s) '()) - (let ((first (parse-eq* s))) - (if (and (dict-literal? first) - (or (null? isdict) (car isdict)) - (eq? (peek-non-newline-token s) 'for)) - (begin - (take-token s) - (parse-dict-comprehension s first closer)) - (let ((t (peek-token s))) - (cond ((or (eqv? t #\,) (eqv? t closer)) - (parse-vect s first closer)) - ((eq? t 'for) - (take-token s) - (parse-comprehension s first closer)) - ((eqv? t #\newline) - (take-token s) - (if (memv (peek-token s) (list #\, closer)) - (parse-vect s first closer) - (parse-matrix s first closer #t))) - (else - (parse-matrix s first closer #f)))))))))) + (let* ((first (parse-eq* s)) + (t (peek-token s))) + (cond ((or (eqv? t #\,) (eqv? t closer)) + (parse-vect s first closer)) + ((eq? t 'for) + (take-token s) + (parse-comprehension s first closer)) + ((eqv? t #\newline) + (take-token s) + (if (memv (peek-token s) (list #\, closer)) + (parse-vect s first closer) + (parse-matrix s first closer #t))) + (else + (parse-matrix s first closer #f)))))))) (define (kw-to-= e) (if (kwarg? e) (cons '= (cdr e)) e)) (define (=-to-kw e) (if (assignment? e) (cons 'kw (cdr e)) e)) @@ -2042,15 +2010,13 @@ (if (eqv? (require-token s) #\}) (begin (take-token s) '(cell1d)) - (let ((vex (parse-cat s #\} #t))) + (let ((vex (parse-cat s #\}))) (if (null? vex) '(cell1d) (case (car vex) ((vect) `(cell1d ,@(cdr vex))) ((hcat) `(cell2d 1 ,(length (cdr vex)) ,@(cdr vex))) ((comprehension) (error "{a for a in b} syntax is discontinued")) - ((dict_comprehension) (error "{a=>b for (a,b) in c} syntax is discontinued")) - ((dict) `(cell1d ,@(cdr vec))) (else (if (and (pair? (cadr vex)) (eq? (caadr vex) 'row)) (let ((nr (length (cdr vex))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4b12960b9b880..9d74378c3fd01 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -275,10 +275,6 @@ (and (symbol? s) (eqv? (string.char (string s) 0) #\#))) -(define (is-call-name? name) - (or (eq? name 'call) (and (pair? name) (sym-ref? name) - (equal? (caddr name) '(inert call))))) - (define (replace-vars e renames) (cond ((symbol? e) (lookup e renames e)) ((or (not (pair? e)) (quoted? e)) e) @@ -331,9 +327,7 @@ (error "function argument and static parameter names must be distinct"))) (if (or (and name (not (sym-ref? name))) (eq? name 'true) (eq? name 'false)) (error (string "invalid function name \"" (deparse name) "\""))) - (let* ((iscall (is-call-name? name)) - (name (if iscall #f name)) - (types (llist-types argl)) + (let* ((types (llist-types argl)) (body (method-lambda-expr argl body rett)) ;; HACK: the typevars need to be bound to ssavalues, since this code ;; might be moved to a different scope by closure-convert. @@ -364,13 +358,6 @@ types))) (call (core svec) ,@temps))) ,body ,isstaged)))) - (if (and iscall (not (null? argl))) - (let* ((n (arg-name (car argl))) - (n (if (hidden-name? n) "" n)) - (t (deparse (arg-type (car argl))))) - (syntax-deprecation #f - (string "call(" n "::" t ", ...)") - (string "(" n "::" t ")(...)")))) (if (symbol? name) `(block (method ,name) ,mdef (unnecessary ,name)) ;; return the function mdef))))) @@ -554,7 +541,7 @@ (list `(... ,(arg-name (car vararg)))))))) #f) ;; return primary function - ,(if (or (not (symbol? name)) (is-call-name? name)) + ,(if (not (symbol? name)) '(null) name))))) ;; prologue includes line number node and eventual meta nodes @@ -1803,13 +1790,8 @@ (eq? (car (cadr e)) 'line)))) (expand-forms (cadr e))) (else - `(block - ,.(map (lambda (x) - (if (and (decl? x) (length= (cdr x) 2) (symbol? (cadr x))) - `(impl-decl ,@(map expand-forms (cdr x))) - (expand-forms x))) - (butlast (cdr e))) - ,(expand-forms (last (cdr e))))))) + (cons 'block + (map expand-forms (cdr e)))))) '|.| (lambda (e) ; e = (|.| f x) @@ -2302,17 +2284,7 @@ ;; TODO: this is a hack to lower simple comprehensions to loops very ;; early, to greatly reduce the # of functions and load on the compiler (lower-comprehension (cadr e) (cadr (caddr e)) ranges)))) - `(call (top collect) ,(cadr e) ,(caddr e))))) - - 'dict_comprehension - (lambda (e) - (syntax-deprecation #f "[a=>b for (a,b) in c]" "Dict(a=>b for (a,b) in c)") - (expand-forms `(call (top Dict) ,(cadr e)))) - - 'typed_dict_comprehension - (lambda (e) (expand-forms - `(call (call (core apply_type) (top Dict) ,@(cdr (cadr e))) - ,(caddr e)))))) + `(call (top collect) ,(cadr e) ,(caddr e))))))) (define (lower-comprehension atype expr ranges) (let ((result (make-ssavalue)) @@ -2644,7 +2616,7 @@ (vinfo:set-called! vi #t)) (for-each (lambda (x) (analyze-vars x env captvars sp)) (cdr e)))) - ((decl impl-decl) + ((decl) ;; handle var::T declaration by storing the type in the var-info ;; record. for non-symbols or globals, emit a type assertion. (let ((vi (var-info-for (cadr e) env))) @@ -3182,21 +3154,15 @@ f(x) = yt(x) (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp)) ;; remaining `decl` expressions are only type assertions if the ;; argument is global or a non-symbol. - ((impl-decl) - (if (or (assq (cadr e) (car (lam:vinfo lam))) - (assq (cadr e) (cadr (lam:vinfo lam)))) - (let ((str-e (deparse `(|::| ,@(cdr e))))) - (syntax-deprecation #f str-e (string "local " str-e)) - '(null)) - (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp))) ((decl) - (cond ((not (symbol? (cadr e))) - (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp)) - ((or (assq (cadr e) (car (lam:vinfo lam))) - (assq (cadr e) (cadr (lam:vinfo lam)))) + (cond ((and (symbol? (cadr e)) + (or (assq (cadr e) (car (lam:vinfo lam))) + (assq (cadr e) (cadr (lam:vinfo lam))))) '(null)) - (else (syntax-deprecation #f (string "global " (deparse `(|::| ,@(cdr e)))) "typeassert") - (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp)))) + (else + (if (or (symbol? (cadr e)) (and (pair? (cadr e)) (eq? (caadr e) 'outerref))) + (error "type declarations on global variables are not yet supported")) + (cl-convert `(call (core typeassert) ,@(cdr e)) fname lam namemap toplevel interp)))) ;; `with-static-parameters` expressions can be removed now; used only by analyze-vars ((with-static-parameters) (cl-convert (cadr e) fname lam namemap toplevel interp)) diff --git a/test/core.jl b/test/core.jl index 12673ffaa271c..db8c87af7f606 100644 --- a/test/core.jl +++ b/test/core.jl @@ -255,6 +255,20 @@ end z = convert(Complex{Float64},2) @test z == Complex(2.0,0.0) +function typeassert_instead_of_decl() + local x + x = 1 + x::Float64 + return 0 +end +@test_throws TypeError typeassert_instead_of_decl() + +# type declarations on globals not implemented yet +@test_throws ErrorException eval(parse("global x20327::Int")) + +y20327 = 1 +@test_throws TypeError y20327::Float64 + # misc fib(n) = n < 2 ? n : fib(n-1) + fib(n-2) @test fib(20) == 6765 diff --git a/test/parse.jl b/test/parse.jl index 35b0e5f96a56f..db79948aedacf 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -438,8 +438,7 @@ let b = IOBuffer(""" end # issue #15763 -# TODO enable post-0.5 -#test_parseerror("if\nfalse\nend", "missing condition in \"if\" at none:1") +test_parseerror("if\nfalse\nend", "missing condition in \"if\" at none:1") test_parseerror("if false\nelseif\nend", "missing condition in \"elseif\" at none:2") # issue #15828 @@ -548,8 +547,6 @@ end # this now is parsed as getindex(Pair{Any,Any}, ...) @test_throws MethodError eval(parse("(Any=>Any)[]")) @test_throws MethodError eval(parse("(Any=>Any)[:a=>1,:b=>2]")) -# to be removed post 0.5 -#@test_throws MethodError eval(parse("(Any=>Any)[x=>y for (x,y) in zip([1,2,3],[4,5,6])]")) # make sure base can be any Integer for T in (Int, BigInt) From 0352af08ac32a2442499ca227130294d439b2d29 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 31 Jan 2017 00:42:15 -0500 Subject: [PATCH 2/2] parse `A=>B` as a `call` --- NEWS.md | 3 +++ base/show.jl | 2 +- base/test.jl | 2 +- src/julia-parser.scm | 12 +++++------- src/julia-syntax.scm | 3 --- test/parse.jl | 2 ++ 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index f8b784ea79c14..efa959b5c5b7f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -166,6 +166,9 @@ This section lists changes that do not have deprecation warnings. that internally uses twice-precision arithmetic. These two outcomes exhibit differences in both precision and speed. + * `A=>B` expressions are now parsed as calls instead of using `=>` as the + expression head ([#20327]). + Library improvements -------------------- diff --git a/base/show.jl b/base/show.jl index f1bbea2d2c6b6..18954fa5855e9 100644 --- a/base/show.jl +++ b/base/show.jl @@ -443,7 +443,7 @@ const uni_ops = Set{Symbol}([:(+), :(-), :(!), :(¬), :(~), :(<:), :(>:), :(√) const expr_infix_wide = Set{Symbol}([ :(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(^=), :(&=), :(|=), :(÷=), :(%=), :(>>>=), :(>>=), :(<<=), :(.=), :(.+=), :(.-=), :(.*=), :(./=), :(.\=), :(.^=), :(.&=), :(.|=), :(.÷=), :(.%=), :(.>>>=), :(.>>=), :(.<<=), - :(&&), :(||), :(<:), :(=>), :($=), :(⊻=)]) # `$=` should be removed after deprecation is removed, issue #18977 + :(&&), :(||), :(<:), :($=), :(⊻=)]) # `$=` should be removed after deprecation is removed, issue #18977 const expr_infix = Set{Symbol}([:(:), :(->), Symbol("::")]) const expr_infix_any = union(expr_infix, expr_infix_wide) const all_ops = union(quoted_syms, uni_ops, expr_infix_any) diff --git a/base/test.jl b/base/test.jl index 30f2b4635ba50..84673e9ba1b42 100644 --- a/base/test.jl +++ b/base/test.jl @@ -954,7 +954,7 @@ function parse_testset_args(args) elseif isa(arg, Expr) && arg.head == :(=) # we're building up a Dict literal here key = Expr(:quote, arg.args[1]) - push!(options.args, Expr(:(=>), key, arg.args[2])) + push!(options.args, Expr(:call, :(=>), key, arg.args[2])) else error("Unexpected argument $arg to @testset") end diff --git a/src/julia-parser.scm b/src/julia-parser.scm index c280447672098..8f7c55f645f25 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -74,7 +74,7 @@ ; operators that are special forms, not function names (define syntactic-operators (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=)) - '(:= --> $= => && |\|\|| |.| ... ->))) + '(:= --> $= && |\|\|| |.| ... ->))) (define syntactic-unary-operators '($ & |::|)) (define syntactic-op? (Set syntactic-operators)) @@ -752,7 +752,9 @@ (begin (ts:put-back! s t) ex) (list 'call t ex (parse-assignment s down))) - (list t ex (parse-assignment s down))))))) + (if (eq? t '=>) ;; ~ and => are the only non-syntactic assignment-precedence operators + (list 'call t ex (parse-assignment s down)) + (list t ex (parse-assignment s down)))))))) (define (parse-eq s) (let ((lno (input-port-line (ts:port s)))) @@ -892,11 +894,7 @@ (else ex)))) (define (invalid-identifier-name? ex) - ;; TODO: remove this hack when we remove the special Dict syntax - ;; TODO: Dict syntax removed, but need to decide whether to change the parsing - ;; of `a=>b` to use `call`. - (or (and (not (eq? ex '=>)) (syntactic-op? ex)) - (eq? ex '....))) + (or (syntactic-op? ex) (eq? ex '....))) (define (parse-unary s) (let ((t (require-token s))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 9d74378c3fd01..282839fdc0025 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2070,9 +2070,6 @@ (error "assignment not allowed inside tuple")) (expand-forms `(call (core tuple) ,@(cdr e)))) - '=> - (lambda (e) `(call => ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) - 'cell1d (lambda (e) (error "{ } vector syntax is discontinued")) 'cell2d (lambda (e) (error "{ } matrix syntax is discontinued")) diff --git a/test/parse.jl b/test/parse.jl index db79948aedacf..93227a3c27354 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -544,6 +544,8 @@ end @test_throws ParseError parse("{x=>y for (x,y) in zip([1,2,3],[4,5,6])}") #@test_throws ParseError parse("{:a=>1, :b=>2}") +@test parse("A=>B") == Expr(:call, :(=>), :A, :B) + # this now is parsed as getindex(Pair{Any,Any}, ...) @test_throws MethodError eval(parse("(Any=>Any)[]")) @test_throws MethodError eval(parse("(Any=>Any)[:a=>1,:b=>2]"))