From 6452535615a83572792f8860508e6ba15adedf04 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 6 Aug 2017 14:29:55 -0400 Subject: [PATCH] rename expression heads for type definitions to match keywords --- NEWS.md | 11 ++++++ base/docs/Docs.jl | 12 +++--- base/show.jl | 6 +-- doc/src/devdocs/ast.md | 4 +- doc/src/devdocs/functions.md | 2 +- doc/src/devdocs/init.md | 8 ++-- src/ast.c | 8 ++-- src/builtins.c | 2 +- src/codegen.cpp | 4 +- src/interpreter.c | 4 +- src/julia-parser.scm | 6 +-- src/julia-syntax.scm | 76 ++++++++++++++++++++---------------- src/julia_internal.h | 4 +- src/macroexpand.scm | 32 +++++++-------- src/method.c | 4 +- 15 files changed, 101 insertions(+), 82 deletions(-) diff --git a/NEWS.md b/NEWS.md index 29cf728efc970..67447c873e804 100644 --- a/NEWS.md +++ b/NEWS.md @@ -35,6 +35,17 @@ Language changes * Nested `if` expressions that arise from the keyword `elseif` now use `elseif` as their expression head instead of `if` ([#21774]). + * Parsed and lowered forms of type definitions have been synchronized with their + new keywords ([#23157]). Expression heads are renamed as follows: + + + `type` => `struct` + + + `bitstype` => `primitive` (order of arguments is also reversed, to match syntax) + + + `composite_type` => `struct_type` + + + `bits_type` => `primitive_type` + Breaking changes ---------------- diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index ef69e30962ff4..90899bbc91254 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -463,7 +463,7 @@ function nameof(x::Expr, ismacro) if isexpr(x, :.) ismacro ? macroname(x) : x else - n = isexpr(x, (:module, :type, :bitstype)) ? 2 : 1 + n = isexpr(x, (:module, :struct)) ? 2 : 1 nameof(x.args[n], ismacro) end end @@ -505,7 +505,7 @@ function metadata(__source__, __module__, expr, ismodule) else push!(args, Pair(:module, __module__)) end - if isexpr(expr, :type) + if isexpr(expr, :struct) # Field docs for concrete types. fields = [] tmp = nothing @@ -685,11 +685,11 @@ function docm(source::LineNumberNode, mod::Module, meta, ex, define = true) # Type definitions. # - # type T ... end - # abstract T - # bitstype N T + # struct T ... end + # abstract type T end + # primitive type T N end # - isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, mod, meta, def, x) : + isexpr(x, [:struct, :abstract, :primitive]) ? objectdoc(source, mod, meta, def, x) : # "Bindings". Names that resolve to objects with different names, ie. # diff --git a/base/show.jl b/base/show.jl index 447423b15298f..0c54db1d9a283 100644 --- a/base/show.jl +++ b/base/show.jl @@ -901,13 +901,13 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, "end") # type declaration - elseif head === :type && nargs==3 + elseif head === :struct && nargs==3 show_block(io, args[1] ? Symbol("mutable struct") : Symbol("struct"), args[2], args[3], indent) print(io, "end") - elseif head === :bitstype && nargs == 2 + elseif head === :primitive && nargs == 2 print(io, "primitive type ") - show_list(io, reverse(args), ' ', indent) + show_list(io, args, ' ', indent) print(io, " end") elseif head === :abstract && nargs == 1 diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index f2968fe91088d..88df6ae64f613 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -516,8 +516,8 @@ end parses as: ``` -(type true (curly Foo (<: T S)) - (block (line 2) (:: x T))) +(struct true (curly Foo (<: T S)) + (block (line 2) (:: x T))) ``` The first argument is a boolean telling whether the type is mutable. diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index f7535eabf9c7a..aa522fc8b8eff 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -243,7 +243,7 @@ The front end generates type declarations for all closures. Initially, this was generating normal type declarations. However, this produced an extremely large number of constructors, all of which were trivial (simply passing all arguments through to `new`). Since methods are partially ordered, inserting all of these methods is O(n^2), plus there are just too many of them to keep -around. This was optimized by generating `composite_type` expressions directly (bypassing default +around. This was optimized by generating `struct_type` expressions directly (bypassing default constructor generation), and using `new` directly to create closure instances. Not the prettiest thing ever, but you do what you gotta do. diff --git a/doc/src/devdocs/init.md b/doc/src/devdocs/init.md index d8e3e2a4f7cc8..78ca22bd6b6db 100644 --- a/doc/src/devdocs/init.md +++ b/doc/src/devdocs/init.md @@ -40,13 +40,13 @@ type description objects for the [built-in types defined in `julia.h`](https://g e.g. ```c -jl_any_type = jl_new_abstracttype(jl_symbol("Any"), NULL, jl_null); +jl_any_type = jl_new_abstracttype(jl_symbol("Any"), core, NULL, jl_emptysvec); jl_any_type->super = jl_any_type; -jl_type_type = jl_new_abstracttype(jl_symbol("Type"), jl_any_type, jl_null); +jl_type_type = jl_new_abstracttype(jl_symbol("Type"), core, jl_any_type, jl_emptysvec); -jl_int32_type = jl_new_bitstype(jl_symbol("Int32"), - jl_any_type, jl_null, 32); +jl_int32_type = jl_new_primitivetype(jl_symbol("Int32"), core, + jl_any_type, jl_emptysvec, 32); ``` [`jl_init_tasks()`](https://github.com/JuliaLang/julia/blob/master/src/task.c) creates the `jl_datatype_t* jl_task_type` diff --git a/src/ast.c b/src/ast.c index 33a709b6d54ef..514e1dfdfb25c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -44,8 +44,8 @@ jl_sym_t *exc_sym; jl_sym_t *error_sym; jl_sym_t *new_sym; jl_sym_t *using_sym; jl_sym_t *const_sym; jl_sym_t *thunk_sym; jl_sym_t *anonymous_sym; jl_sym_t *underscore_sym; -jl_sym_t *abstracttype_sym; jl_sym_t *bitstype_sym; -jl_sym_t *compositetype_sym; jl_sym_t *foreigncall_sym; +jl_sym_t *abstracttype_sym; jl_sym_t *primtype_sym; +jl_sym_t *structtype_sym; jl_sym_t *foreigncall_sym; jl_sym_t *global_sym; jl_sym_t *list_sym; jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym; @@ -414,8 +414,8 @@ void jl_init_frontend(void) underscore_sym = jl_symbol("_"); amp_sym = jl_symbol("&"); abstracttype_sym = jl_symbol("abstract_type"); - bitstype_sym = jl_symbol("bits_type"); - compositetype_sym = jl_symbol("composite_type"); + primtype_sym = jl_symbol("primitive_type"); + structtype_sym = jl_symbol("struct_type"); toplevel_sym = jl_symbol("toplevel"); dot_sym = jl_symbol("."); boundscheck_sym = jl_symbol("boundscheck"); diff --git a/src/builtins.c b/src/builtins.c index 3b0b39faeab82..4d099f4156a8a 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -600,7 +600,7 @@ JL_CALLABLE(jl_f_svec) return (jl_value_t*)t; } -// composite types ------------------------------------------------------------ +// struct operations ------------------------------------------------------------ JL_CALLABLE(jl_f_getfield) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 8724918761ee1..9228f15fe51d2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3859,8 +3859,8 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr) ctx.builder.CreateCall(prepare_call(jltopeval_func), args); return ghostValue(jl_void_type); } - if (head == abstracttype_sym || head == compositetype_sym || - head == bitstype_sym) { + if (head == abstracttype_sym || head == structtype_sym || + head == primtype_sym) { jl_errorf("type definition not allowed inside a local scope"); } else { diff --git a/src/interpreter.c b/src/interpreter.c index c1ebb4ff6f3d6..3b6ba070e5ec3 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -391,7 +391,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) JL_GC_POP(); return (jl_value_t*)jl_nothing; } - else if (ex->head == bitstype_sym) { + else if (ex->head == primtype_sym) { if (inside_typedef) jl_error("cannot eval a new bits type definition while defining another type"); jl_value_t *name = args[0]; @@ -439,7 +439,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) JL_GC_POP(); return (jl_value_t*)jl_nothing; } - else if (ex->head == compositetype_sym) { + else if (ex->head == structtype_sym) { if (inside_typedef) jl_error("cannot eval a new data type definition while defining another type"); jl_value_t *name = args[0]; diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 07241df9a1a82..b7ca3a19577c6 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1252,7 +1252,7 @@ (if (reserved-word? (peek-token s)) (error (string "invalid type name \"" (take-token s) "\""))) (let ((sig (parse-subtype-spec s))) - (begin0 (list 'type (if mut? 'true 'false) sig (parse-block s)) + (begin0 (list 'struct (if mut? 'true 'false) sig (parse-block s)) (expect-end s word)))) ;; consume any number of line endings from a token stream @@ -1400,7 +1400,7 @@ (begin (take-token s) (let* ((spec (with-space-sensitive (parse-subtype-spec s))) (nb (with-space-sensitive (parse-cond s)))) - (begin0 (list 'bitstype nb spec) + (begin0 (list 'primitive spec nb) (expect-end (take-lineendings s) "primitive type")))))) ;; deprecated type keywords ((type) @@ -1414,7 +1414,7 @@ (spec (parse-subtype-spec s))) (syntax-deprecation s (string "bitstype " (deparse nb) " " (deparse spec)) (string "primitive type " (deparse spec) " " (deparse nb) " end")) - (list 'bitstype nb spec))) + (list 'primitive spec nb))) ((typealias) (let ((lhs (with-space-sensitive (parse-call s))) (rhs (parse-where s parse-call))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index dd1a5c24a7203..0de5a2173306a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -887,9 +887,9 @@ (global ,name) (const ,name) ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) - (composite_type ,name (call (core svec) ,@params) - (call (core svec) ,@(map (lambda (x) `',x) field-names)) - ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) + (struct_type ,name (call (core svec) ,@params) + (call (core svec) ,@(map (lambda (x) `',x) field-names)) + ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) ;; "inner" constructors (scope-block (block @@ -925,7 +925,7 @@ ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) (abstract_type ,name (call (core svec) ,@params) ,super)))))) -(define (bits-def-expr n name params super) +(define (primitive-type-def-expr n name params super) (receive (params bounds) (sparam-name-bounds params) `(block @@ -934,7 +934,7 @@ (block ,@(map (lambda (v) `(local ,v)) params) ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) - (bits_type ,name (call (core svec) ,@params) ,n ,super)))))) + (primitive_type ,name (call (core svec) ,@params) ,n ,super)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} (define (analyze-type-sig ex) @@ -1188,7 +1188,7 @@ (else (error "invalid macro definition")))) -(define (expand-type-def e) +(define (expand-struct-def e) (let ((mut (cadr e)) (sig (caddr e)) (fields (cdr (cadddr e)))) @@ -1892,7 +1892,11 @@ '-> expand-arrow 'let expand-let 'macro expand-macro-def - 'type expand-type-def + 'struct expand-struct-def + 'type + (lambda (e) + (syntax-deprecation #f ":type expression head" ":struct") + (expand-struct-def e)) 'try expand-try ;; deprecated in 0.6 'typealias (lambda (e) (expand-typealias (cadr e) (caddr e))) @@ -2084,11 +2088,15 @@ 'bitstype (lambda (e) - (let ((n (cadr e)) - (sig (caddr e))) + (syntax-deprecation #f "Expr(:bitstype, nbits, name)" "Expr(:primitive, name, nbits)") + (expand-forms `(primitive ,(caddr e) ,(cadr e)))) + 'primitive + (lambda (e) + (let ((sig (cadr e)) + (n (caddr e))) (expand-forms (receive (name params super) (analyze-type-sig sig) - (bits-def-expr n name params super))))) + (primitive-type-def-expr n name params super))))) 'comparison (lambda (e) (expand-forms (expand-compare-chain (cdr e)))) @@ -2781,21 +2789,21 @@ f(x) = yt(x) (() () 0 ()) (body (global ,name) (const ,name) ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) 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)) + (struct_type ,name (call (core svec) ,@P) + (call (core svec) ,@(map (lambda (v) `',v) fields)) + ,super + (call (core svec) ,@types) false ,(length fields)) (return (null)))))))) (define (type-for-closure name fields super) `((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) '(core Any)) fields)) - false ,(length fields)) + (struct_type ,name (call (core svec)) + (call (core svec) ,@(map (lambda (v) `',v) fields)) + ,super + (call (core svec) ,@(map (lambda (v) '(core Any)) fields)) + false ,(length fields)) (return (null))))))) @@ -2808,20 +2816,20 @@ f(x) = yt(x) ; `((global ,name) ; (const ,name) ; ,@(map (lambda (p n) `(= ,p (call (core TypeVar) ',n (core Any)))) 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))))) +; (struct_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)))) +; (struct_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) @@ -3634,25 +3642,25 @@ f(x) = yt(x) ((isdefined) (if tail (emit-return e) e)) ;; top level expressions returning values - ((abstract_type bits_type composite_type thunk toplevel module) + ((abstract_type primitive_type struct_type thunk toplevel module) (case (car e) ((abstract_type) (let* ((para (compile (caddr e) break-labels #t #f)) (supe (compile (cadddr e) break-labels #t #f))) (emit `(abstract_type ,(cadr e) ,para ,supe)))) - ((bits_type) + ((primitive_type) (let* ((para (compile (caddr e) break-labels #t #f)) (supe (compile (list-ref e 4) break-labels #t #f))) - (emit `(bits_type ,(cadr e) ,para ,(cadddr e) ,supe)))) - ((composite_type) + (emit `(primitive_type ,(cadr e) ,para ,(cadddr e) ,supe)))) + ((struct_type) (let* ((para (compile (caddr e) break-labels #t #f)) (supe (compile (list-ref e 4) break-labels #t #f)) - ;; composite_type has an unconventional evaluation rule that + ;; struct_type has an unconventional evaluation rule that ;; needs to do work around the evaluation of the field types, ;; so the field type expressions need to be kept in place as ;; much as possible. (part of issue #21923) (ftys (compile (list-ref e 5) break-labels #t #f #f))) - (emit `(composite_type ,(cadr e) ,para ,(cadddr e) ,supe ,ftys ,@(list-tail e 6))))) + (emit `(struct_type ,(cadr e) ,para ,(cadddr e) ,supe ,ftys ,@(list-tail e 6))))) (else (emit e))) (if tail (emit-return '(null))) diff --git a/src/julia_internal.h b/src/julia_internal.h index 1ab4168897438..5d9ada3f02933 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -986,8 +986,8 @@ extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym; extern jl_sym_t *compiler_temp_sym; extern jl_sym_t *foreigncall_sym; extern jl_sym_t *const_sym; extern jl_sym_t *thunk_sym; extern jl_sym_t *anonymous_sym; extern jl_sym_t *underscore_sym; -extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym; -extern jl_sym_t *compositetype_sym; +extern jl_sym_t *abstracttype_sym; extern jl_sym_t *primtype_sym; +extern jl_sym_t *structtype_sym; extern jl_sym_t *global_sym; extern jl_sym_t *unused_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym; extern jl_sym_t *copyast_sym; extern jl_sym_t *fastmath_sym; diff --git a/src/macroexpand.scm b/src/macroexpand.scm index c72746bb1e614..ba99b97daaffc 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -133,15 +133,15 @@ (if var (list 'varlist var) '())) ;; type definition - (pattern-lambda (type mut (<: (curly tn . tvars) super) body) + (pattern-lambda (struct mut (<: (curly tn . tvars) super) body) (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) (typevar-names tvars))) - (pattern-lambda (type mut (curly tn . tvars) body) + (pattern-lambda (struct mut (curly tn . tvars) body) (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) (typevar-names tvars))) - (pattern-lambda (type mut (<: tn super) body) + (pattern-lambda (struct mut (<: tn super) body) (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) - (pattern-lambda (type mut tn body) + (pattern-lambda (struct mut tn body) (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) )) ; vars-introduced-by-patterns @@ -315,18 +315,18 @@ ((macrocall) e) ; invalid syntax anyways, so just act like it's quoted. ((symboliclabel) e) ((symbolicgoto) e) - ((type) - `(type ,(cadr e) ,(resolve-expansion-vars- (caddr e) env m parent-scope inarg) - ;; type has special behavior: identifiers inside are - ;; field names, not expressions. - ,(map (lambda (x) - (cond ((atom? x) x) - ((and (pair? x) (eq? (car x) '|::|)) - `(|::| ,(cadr x) - ,(resolve-expansion-vars- (caddr x) env m parent-scope inarg))) - (else - (resolve-expansion-vars-with-new-env x env m parent-scope inarg)))) - (cadddr e)))) + ((struct) + `(struct ,(cadr e) ,(resolve-expansion-vars- (caddr e) env m parent-scope inarg) + ;; type has special behavior: identifiers inside are + ;; field names, not expressions. + ,(map (lambda (x) + (cond ((atom? x) x) + ((and (pair? x) (eq? (car x) '|::|)) + `(|::| ,(cadr x) + ,(resolve-expansion-vars- (caddr x) env m parent-scope inarg))) + (else + (resolve-expansion-vars-with-new-env x env m parent-scope inarg)))) + (cadddr e)))) ((parameters) (cons 'parameters diff --git a/src/method.c b/src/method.c index db2d44e8369fc..f7ed0d20b9b03 100644 --- a/src/method.c +++ b/src/method.c @@ -104,8 +104,8 @@ jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t JL_TYPECHK(ccall method definition, symbol, *(jl_value_t**)jl_exprarg(e, 3)); JL_TYPECHK(ccall method definition, long, jl_exprarg(e, 4)); } - if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym || - e->head == bitstype_sym || e->head == module_sym) { + if (e->head == method_sym || e->head == abstracttype_sym || e->head == structtype_sym || + e->head == primtype_sym || e->head == module_sym) { i++; } for (; i < nargs; i++) {