From f8acac74c5c48e00c967f75ea93c9bf08d3f6122 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 7 Feb 2018 23:12:34 -0500 Subject: [PATCH] complete `deparse` in front end. fixes #24549 (#25937) --- src/ast.scm | 266 ++++++++++++++++++++++++++++++++++--------------- test/syntax.jl | 2 +- 2 files changed, 184 insertions(+), 84 deletions(-) diff --git a/src/ast.scm b/src/ast.scm index bd8944157f274..4f7024ecee025 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -16,17 +16,33 @@ (deparse head)) opn (deparse-arglist args) cls)) -(define (deparse e) - (define (block-stmts e) - (if (and (pair? e) (eq? (car e) 'block)) - (cdr e) - (list e))) - (define (deparse-block head lst) - (string head "\n" - (string.join (map (lambda (ex) (string " " (deparse ex))) - lst) - "\n") - "\nend")) +(define (deparse-generator e) + (if (eq? (car e) 'flatten) + (deparse-flatten e '()) + (string (deparse (cadr e)) " for " (deparse-arglist (cddr e) ", ")))) + +(define (deparse-flatten e iters (flat #t)) + (cond ((and flat (pair? e) (eq? (car e) 'generator)) + (deparse-flatten (cadr e) (cons (deparse-arglist (cddr e) ", ") iters) #f)) + ((and flat (pair? e) (eq? (car e) 'flatten)) + (let ((e (cadr e))) + (deparse-flatten (cadr e) (cons (deparse-arglist (cddr e) ", ") iters) #t))) + (else + (string (deparse e) " for " (string.join (reverse iters) " for "))))) + +(define (indented-block lst ilvl) + (string + (string.join (map (lambda (ex) (string (string.rep " " (+ ilvl 1)) + (deparse ex (+ ilvl 1)))) + lst) + "\n") + (if (null? lst) "" "\n"))) + +(define (deparse-block head lst ilvl) + (string head "\n" (indented-block lst ilvl) + (string.rep " " ilvl) "end")) + +(define (deparse e (ilvl 0)) (cond ((or (symbol? e) (number? e)) (string e)) ((string? e) (print-to-string e)) ((eq? e #t) "true") @@ -53,78 +69,162 @@ (if (length= e 2) (string (car e) (deparse (cadr e))) (string (deparse (cadr e)) " " (car e) " " (deparse (caddr e))))) - ((memq (car e) '($ &)) - (if (pair? (cadr e)) - (string (car e) "(" (deparse (cadr e)) ")") - (string (car e) (deparse (cadr e))))) - ((eq? (car e) '|::|) - (if (length> e 2) - (string (deparse (cadr e)) (car e) (deparse (caddr e))) - (string (car e) (deparse (cadr e))))) - (else (case (car e) - ((tuple) - (string #\( (deparse-arglist (cdr e)) - (if (length= e 2) #\, "") - #\))) - ((call) (deparse-prefix-call (cadr e) (cddr e) #\( #\))) - ((curly) (deparse-prefix-call (cadr e) (cddr e) #\{ #\})) - ((ref) (deparse-prefix-call (cadr e) (cddr e) #\[ #\])) - ((macrocall) (string (cadr e) " " (deparse-arglist (cddr e) " "))) - ((quote inert) - (if (and (symbol? (cadr e)) - (not (= (string.char (string (cadr e)) 0) #\=))) - (string ":" (deparse (cadr e))) - (string ":(" (deparse (cadr e)) ")"))) - ((vect) (string #\[ (deparse-arglist (cdr e) ", ") #\])) - ((vcat) (string #\[ (deparse-arglist (cdr e) "; ") #\])) - ((typed_vcat) (string (deparse (cadr e)) - (deparse (cons 'vcat (cddr e))))) - ((hcat) (string #\[ (deparse-arglist (cdr e) " ") #\])) - ((typed_hcat) (string (deparse (cadr e)) - (deparse (cons 'hcat (cddr e))))) - ((row) (deparse-arglist (cdr e) " ")) - ((braces) (string #\{ (deparse-arglist (cdr e) ", ") #\})) - ((bracescat) (string #\{ (deparse-arglist (cdr e) "; ") #\})) - ((const) (string "const " (deparse (cadr e)))) - ((global local) - (string (car e) " " (string.join (map deparse (cdr e)) ", "))) - ((top) (deparse (cadr e))) - ((core) (string "Core." (deparse (cadr e)))) - ((globalref) (string (deparse (cadr e)) "." (deparse (caddr e)))) - ((outerref) (string (deparse (cadr e)))) - ((:) - (string (deparse (cadr e)) ': (deparse (caddr e)) - (if (length> e 3) - (string ': (deparse (cadddr e))) - ""))) - ((comparison) (apply string (map deparse (cdr e)))) - ((in) (string (deparse (cadr e)) " in " (deparse (caddr e)))) - ((ssavalue) (string "SSAValue(" (cadr e) ")")) - ((line) (if (length= e 2) - (string "# line " (cadr e)) - (string "# " (caddr e) ", line " (cadr e)))) - ((block) - (deparse-block "begin" (cdr e))) - ((comprehension) - (let ((e (cadr e))) - (string "[ " (deparse (cadr e)) " for " (deparse-arglist (cddr e) ", ") " ]"))) - ((typed_comprehension) - (string (deparse (cadr e)) - (deparse (cons 'comprehension (cddr e))))) - ((generator) - (string "(" (deparse (cadr e)) " for " (deparse-arglist (cddr e) ", ") ")")) - ((where) - (string (deparse (cadr e)) " where " - (if (length= e 3) - (deparse (caddr e)) - (deparse (cons 'braces (cddr e)))))) - ((function for while) - (deparse-block (string (car e) " " (deparse (cadr e))) - (block-stmts (caddr e)))) - ((copyast) (deparse (cadr e))) - ((kw) (string (deparse (cadr e)) " = " (deparse (caddr e)))) - (else - (string e)))))) + (else + (case (car e) + ;; calls and operators + ((call) + (if (and (length= e 4) (operator? (cadr e))) + (string #\( (deparse (caddr e)) " " (cadr e) " " (deparse (cadddr e)) #\) ) + (deparse-prefix-call (cadr e) (cddr e) #\( #\)))) + (($ &) (if (pair? (cadr e)) + (string (car e) "(" (deparse (cadr e)) ")") + (string (car e) (deparse (cadr e))))) + ((|::|) (if (length= e 2) + (string (car e) (deparse (cadr e))) + (string (deparse (cadr e)) (car e) (deparse (caddr e))))) + ((comparison) (string.join (map deparse (cdr e)) " ")) + ((:) (string (deparse (cadr e)) ': (deparse (caddr e)) + (if (length> e 3) + (string ': (deparse (cadddr e))) + ""))) + ((macrocall) (string (cadr e) " " (deparse-arglist (cddr e) " "))) + ((kw) (string (deparse (cadr e)) " = " (deparse (caddr e)))) + ((where) (string (deparse (cadr e)) " where " + (if (length= e 3) + (deparse (caddr e)) + (deparse (cons 'braces (cddr e)))))) + ;; bracket forms + ((tuple) + (string #\( (deparse-arglist (cdr e)) + (if (length= e 2) #\, "") + #\))) + ((ref) (deparse-prefix-call (cadr e) (cddr e) #\[ #\])) + ((curly) (deparse-prefix-call (cadr e) (cddr e) #\{ #\})) + ((vect) (string #\[ (deparse-arglist (cdr e) ", ") #\])) + ((vcat) (string #\[ (deparse-arglist (cdr e) "; ") #\])) + ((typed_vcat) (string (deparse (cadr e)) + (deparse (cons 'vcat (cddr e))))) + ((hcat) (string #\[ (deparse-arglist (cdr e) " ") #\])) + ((typed_hcat) (string (deparse (cadr e)) + (deparse (cons 'hcat (cddr e))))) + ((row) (deparse-arglist (cdr e) " ")) + ((braces) (string #\{ (deparse-arglist (cdr e) ", ") #\})) + ((bracescat) (string #\{ (deparse-arglist (cdr e) "; ") #\})) + ((string) + (string #\" + (string.join + (map (lambda (s) + (cond ((string? s) s) + ((symbol? s) (string "$" s)) + (else (string "$(" (deparse s) ")")))) + (cdr e)) + "") + #\")) + ;; comprehensions and generators + ((generator) (string "(" (deparse-generator e) ")")) + ((flatten) (string "(" (deparse-generator e) ")")) + ((filter) (string (deparse (caddr e)) " if " (deparse (cadr e)))) + ((comprehension) (string "[ " (deparse-generator (cadr e)) " ]")) + ((typed_comprehension) + (string (deparse (cadr e)) + (deparse (cons 'comprehension (cddr e))))) + ;; block forms + ((block) (deparse-block "begin" (cdr e) ilvl)) + ((toplevel) (string.join (map deparse (cdr e)) "\n")) + ((function macro for while) + (define (block-stmts e) + (if (and (pair? e) (eq? (car e) 'block)) + (cdr e) + (list e))) + (deparse-block (string (car e) " " (deparse (cadr e))) + (block-stmts (caddr e)) + ilvl)) + ((return) (string "return " (deparse (cadr e)))) + ((break continue) (string (car e))) + ((if elseif) + (define (if-cond e) + (if (eq? (car e) 'elseif) + (caddr (cadr e)) + (cadr e))) + (if (length= e 3) + (deparse-block (string (car e) " " (deparse (if-cond e))) + (cdr (caddr e)) ilvl) + (string (car e) " " (deparse (if-cond e)) "\n" + (indented-block (cdr (caddr e)) ilvl) + (let ((els (cadddr e))) + (if (and (pair? els) (eq? (car els) 'elseif)) + (deparse els) + (deparse-block "else" (cdr els) ilvl)))))) + ((let) + (deparse-block (string "let " (string.join (map deparse (cdadr e)) ", ")) + (cdr (caddr e)) ilvl)) + ((try) + (string "try\n" + (indented-block (cdr (cadr e)) ilvl) + (if (and (pair? (cadddr e)) (eq? (car (cadddr e)) 'block)) + (string (string.rep " " ilvl) "catch" + (if (eq? (caddr e) 'false) + "" + (string " " (caddr e))) + "\n" + (indented-block (cdr (cadddr e)) ilvl)) + "") + (if (length> e 4) + (let ((fin (caddddr e))) + (if (and (pair? fin) (eq? (car fin) 'block)) + (string (string.rep " " ilvl) "finally\n" + (indented-block (cdr fin) ilvl)) + "")) + "") + (string.rep " " ilvl) "end")) + ((struct) + (string (if (eq? (cadr e) 'true) "mutable " "") + "struct " + (deparse-block (deparse (caddr e)) (cdr (cadddr e)) ilvl))) + ((abstract) + (string "abstract type " (deparse (cadr e)) " end")) + ((primitive) + (string "primitive type " (deparse (cadr e)) " " (deparse (caddr e)) " end")) + ((module) + (string (if (eq? (cadr e) 'true) "module " "baremodule ") + (caddr e) "\n" + (string.join (map deparse (cdr (cadddr e))) "\n") "\n" + "end")) + ;; misc syntax forms + ((import importall using) + (define (deparse-path e) + (cond ((and (pair? e) (eq? (car e) '|.|)) + (let loop ((lst (cdr e)) + (ndots 0)) + (if (or (null? lst) + (not (eq? (car lst) '|.|))) + (string (string.rep "." ndots) + (string.join (map deparse lst) ".")) + (loop (cdr lst) (+ ndots 1))))) + ((and (pair? e) (eq? (car e) ':)) + (string (deparse-path (cadr e)) ": " + (string.join (map deparse-path (cddr e)) ", "))) + (else + (string e)))) + (string (car e) " " (string.join (map deparse-path (cdr e)) ", "))) + ((global local export) (string (car e) " " (string.join (map deparse (cdr e)) ", "))) + ((const) (string "const " (deparse (cadr e)))) + ((top) (deparse (cadr e))) + ((core) (string "Core." (deparse (cadr e)))) + ((globalref) (string (deparse (cadr e)) "." (deparse (caddr e)))) + ((outerref) (string (deparse (cadr e)))) + ((ssavalue) (string "SSAValue(" (cadr e) ")")) + ((line) (if (length= e 2) + (string "# line " (cadr e)) + (string "# " (caddr e) ", line " (cadr e)))) + ((copyast) (deparse (cadr e))) + ((quote inert) + (if (and (symbol? (cadr e)) + (not (= (string.char (string (cadr e)) 0) #\=))) + (string ":" (deparse (cadr e))) + (string ":(" (deparse (cadr e)) ")"))) + (else + (string e)))))) ;; custom gensyms diff --git a/test/syntax.jl b/test/syntax.jl index 0971c4109fbf3..2cae098ee11be 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -634,7 +634,7 @@ for op in ["+", "-", "\$", "|", ".+", ".-", "*", ".*"] end # issue #17701 -@test Meta.lower(Main, :(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"==(i, 3) && i\"") +@test Meta.lower(Main, :(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"(i == 3) && i\"") # issue #18667 @test Meta.lower(Main, :(true = 1)) == Expr(:error, "invalid assignment location \"true\"")