Skip to content

Commit 6634dc2

Browse files
committed
Move Meta function exports into meta.jl
Allows using meta.jl much earlier in the build (instead of importing these from show.jl).
1 parent d268106 commit 6634dc2

File tree

3 files changed

+118
-115
lines changed

3 files changed

+118
-115
lines changed

base/Base.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ let os = ccall(:jl_get_UNAME, Any, ())
3030
end
3131
end
3232

33+
# metaprogramming
34+
include("meta.jl")
35+
3336
# subarrays
3437
include("subarray.jl")
3538
include("views.jl")
@@ -157,9 +160,6 @@ include("weakkeydict.jl")
157160
# ScopedValues
158161
include("scopedvalues.jl")
159162

160-
# metaprogramming
161-
include("meta.jl")
162-
163163
# Logging
164164
include("logging/logging.jl")
165165
using .CoreLogging

base/meta.jl

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,121 @@ export quot,
1818

1919
public parse
2020

21-
using Base: isidentifier, isoperator, isunaryoperator, isbinaryoperator, ispostfixoperator
2221
import Base: isexpr
2322

23+
## AST decoding helpers ##
24+
25+
is_id_start_char(c::AbstractChar) = ccall(:jl_id_start_char, Cint, (UInt32,), c) != 0
26+
is_id_char(c::AbstractChar) = ccall(:jl_id_char, Cint, (UInt32,), c) != 0
27+
28+
"""
29+
isidentifier(s) -> Bool
30+
31+
Return whether the symbol or string `s` contains characters that are parsed as
32+
a valid ordinary identifier (not a binary/unary operator) in Julia code;
33+
see also [`Base.isoperator`](@ref).
34+
35+
Internally Julia allows any sequence of characters in a `Symbol` (except `\\0`s),
36+
and macros automatically use variable names containing `#` in order to avoid
37+
naming collision with the surrounding code. In order for the parser to
38+
recognize a variable, it uses a limited set of characters (greatly extended by
39+
Unicode). `isidentifier()` makes it possible to query the parser directly
40+
whether a symbol contains valid characters.
41+
42+
# Examples
43+
```jldoctest
44+
julia> Meta.isidentifier(:x), Meta.isidentifier("1x")
45+
(true, false)
46+
```
47+
"""
48+
function isidentifier(s::AbstractString)
49+
x = Iterators.peel(s)
50+
isnothing(x) && return false
51+
(s == "true" || s == "false") && return false
52+
c, rest = x
53+
is_id_start_char(c) || return false
54+
return all(is_id_char, rest)
55+
end
56+
isidentifier(s::Symbol) = isidentifier(string(s))
57+
58+
is_op_suffix_char(c::AbstractChar) = ccall(:jl_op_suffix_char, Cint, (UInt32,), c) != 0
59+
60+
_isoperator(s) = ccall(:jl_is_operator, Cint, (Cstring,), s) != 0
61+
62+
"""
63+
isoperator(s::Symbol)
64+
65+
Return `true` if the symbol can be used as an operator, `false` otherwise.
66+
67+
# Examples
68+
```jldoctest
69+
julia> Meta.isoperator(:+), Meta.isoperator(:f)
70+
(true, false)
71+
```
72+
"""
73+
isoperator(s::Union{Symbol,AbstractString}) = _isoperator(s) || ispostfixoperator(s)
74+
75+
"""
76+
isunaryoperator(s::Symbol)
77+
78+
Return `true` if the symbol can be used as a unary (prefix) operator, `false` otherwise.
79+
80+
# Examples
81+
```jldoctest
82+
julia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)
83+
(true, true, false)
84+
```
85+
"""
86+
isunaryoperator(s::Symbol) = ccall(:jl_is_unary_operator, Cint, (Cstring,), s) != 0
87+
is_unary_and_binary_operator(s::Symbol) = ccall(:jl_is_unary_and_binary_operator, Cint, (Cstring,), s) != 0
88+
is_syntactic_operator(s::Symbol) = ccall(:jl_is_syntactic_operator, Cint, (Cstring,), s) != 0
89+
90+
"""
91+
isbinaryoperator(s::Symbol)
92+
93+
Return `true` if the symbol can be used as a binary (infix) operator, `false` otherwise.
94+
95+
# Examples
96+
```jldoctest
97+
julia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)
98+
(true, false, false)
99+
```
100+
"""
101+
function isbinaryoperator(s::Symbol)
102+
return _isoperator(s) && (!isunaryoperator(s) || is_unary_and_binary_operator(s)) &&
103+
s !== Symbol("'")
104+
end
105+
106+
"""
107+
ispostfixoperator(s::Union{Symbol,AbstractString})
108+
109+
Return `true` if the symbol can be used as a postfix operator, `false` otherwise.
110+
111+
# Examples
112+
```jldoctest
113+
julia> Meta.ispostfixoperator(Symbol("'")), Meta.ispostfixoperator(Symbol("'ᵀ")), Meta.ispostfixoperator(:-)
114+
(true, true, false)
115+
```
116+
"""
117+
function ispostfixoperator(s::Union{Symbol,AbstractString})
118+
s = String(s)::String
119+
return startswith(s, '\'') && all(is_op_suffix_char, SubString(s, 2))
120+
end
121+
122+
const keyword_syms = IdSet{Symbol}([
123+
:baremodule, :begin, :break, :catch, :const, :continue, :do, :else, :elseif,
124+
:end, :export, :var"false", :finally, :for, :function, :global, :if, :import,
125+
:let, :local, :macro, :module, :public, :quote, :return, :struct, :var"true",
126+
:try, :using, :while ])
127+
128+
function is_valid_identifier(sym)
129+
return (isidentifier(sym) && !(sym in keyword_syms)) ||
130+
(_isoperator(sym) &&
131+
!(sym in (Symbol("'"), :(::), :?)) &&
132+
!is_syntactic_operator(sym)
133+
)
134+
end
135+
24136
"""
25137
Meta.quot(ex)::Expr
26138

base/show.jl

Lines changed: 2 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

33
using .Compiler: has_typevar
4+
using .Meta: isidentifier, isoperator, isunaryoperator, isbinaryoperator, ispostfixoperator,
5+
is_id_start_char, is_id_char, _isoperator, is_syntactic_operator, is_valid_identifier
46

57
function show(io::IO, ::MIME"text/plain", u::UndefInitializer)
68
show(io, u)
@@ -1542,104 +1544,6 @@ const expr_parens = Dict(:tuple=>('(',')'), :vcat=>('[',']'),
15421544
:ncat =>('[',']'), :nrow =>('[',']'),
15431545
:braces=>('{','}'), :bracescat=>('{','}'))
15441546

1545-
## AST decoding helpers ##
1546-
1547-
is_id_start_char(c::AbstractChar) = ccall(:jl_id_start_char, Cint, (UInt32,), c) != 0
1548-
is_id_char(c::AbstractChar) = ccall(:jl_id_char, Cint, (UInt32,), c) != 0
1549-
1550-
"""
1551-
isidentifier(s) -> Bool
1552-
1553-
Return whether the symbol or string `s` contains characters that are parsed as
1554-
a valid ordinary identifier (not a binary/unary operator) in Julia code;
1555-
see also [`Base.isoperator`](@ref).
1556-
1557-
Internally Julia allows any sequence of characters in a `Symbol` (except `\\0`s),
1558-
and macros automatically use variable names containing `#` in order to avoid
1559-
naming collision with the surrounding code. In order for the parser to
1560-
recognize a variable, it uses a limited set of characters (greatly extended by
1561-
Unicode). `isidentifier()` makes it possible to query the parser directly
1562-
whether a symbol contains valid characters.
1563-
1564-
# Examples
1565-
```jldoctest
1566-
julia> Meta.isidentifier(:x), Meta.isidentifier("1x")
1567-
(true, false)
1568-
```
1569-
"""
1570-
function isidentifier(s::AbstractString)
1571-
x = Iterators.peel(s)
1572-
isnothing(x) && return false
1573-
(s == "true" || s == "false") && return false
1574-
c, rest = x
1575-
is_id_start_char(c) || return false
1576-
return all(is_id_char, rest)
1577-
end
1578-
isidentifier(s::Symbol) = isidentifier(string(s))
1579-
1580-
is_op_suffix_char(c::AbstractChar) = ccall(:jl_op_suffix_char, Cint, (UInt32,), c) != 0
1581-
1582-
_isoperator(s) = ccall(:jl_is_operator, Cint, (Cstring,), s) != 0
1583-
1584-
"""
1585-
isoperator(s::Symbol)
1586-
1587-
Return `true` if the symbol can be used as an operator, `false` otherwise.
1588-
1589-
# Examples
1590-
```jldoctest
1591-
julia> Meta.isoperator(:+), Meta.isoperator(:f)
1592-
(true, false)
1593-
```
1594-
"""
1595-
isoperator(s::Union{Symbol,AbstractString}) = _isoperator(s) || ispostfixoperator(s)
1596-
1597-
"""
1598-
isunaryoperator(s::Symbol)
1599-
1600-
Return `true` if the symbol can be used as a unary (prefix) operator, `false` otherwise.
1601-
1602-
# Examples
1603-
```jldoctest
1604-
julia> Meta.isunaryoperator(:-), Meta.isunaryoperator(:√), Meta.isunaryoperator(:f)
1605-
(true, true, false)
1606-
```
1607-
"""
1608-
isunaryoperator(s::Symbol) = ccall(:jl_is_unary_operator, Cint, (Cstring,), s) != 0
1609-
is_unary_and_binary_operator(s::Symbol) = ccall(:jl_is_unary_and_binary_operator, Cint, (Cstring,), s) != 0
1610-
is_syntactic_operator(s::Symbol) = ccall(:jl_is_syntactic_operator, Cint, (Cstring,), s) != 0
1611-
1612-
"""
1613-
isbinaryoperator(s::Symbol)
1614-
1615-
Return `true` if the symbol can be used as a binary (infix) operator, `false` otherwise.
1616-
1617-
# Examples
1618-
```jldoctest
1619-
julia> Meta.isbinaryoperator(:-), Meta.isbinaryoperator(:√), Meta.isbinaryoperator(:f)
1620-
(true, false, false)
1621-
```
1622-
"""
1623-
function isbinaryoperator(s::Symbol)
1624-
return _isoperator(s) && (!isunaryoperator(s) || is_unary_and_binary_operator(s)) &&
1625-
s !== Symbol("'")
1626-
end
1627-
1628-
"""
1629-
ispostfixoperator(s::Union{Symbol,AbstractString})
1630-
1631-
Return `true` if the symbol can be used as a postfix operator, `false` otherwise.
1632-
1633-
# Examples
1634-
```jldoctest
1635-
julia> Meta.ispostfixoperator(Symbol("'")), Meta.ispostfixoperator(Symbol("'ᵀ")), Meta.ispostfixoperator(:-)
1636-
(true, true, false)
1637-
```
1638-
"""
1639-
function ispostfixoperator(s::Union{Symbol,AbstractString})
1640-
s = String(s)::String
1641-
return startswith(s, '\'') && all(is_op_suffix_char, SubString(s, 2))
1642-
end
16431547

16441548
"""
16451549
operator_precedence(s::Symbol)
@@ -1778,19 +1682,6 @@ function show_enclosed_list(io::IO, op, items, sep, cl, indent, prec=0, quote_le
17781682
print(io, cl)
17791683
end
17801684

1781-
const keyword_syms = Set([
1782-
:baremodule, :begin, :break, :catch, :const, :continue, :do, :else, :elseif,
1783-
:end, :export, :var"false", :finally, :for, :function, :global, :if, :import,
1784-
:let, :local, :macro, :module, :public, :quote, :return, :struct, :var"true",
1785-
:try, :using, :while ])
1786-
1787-
function is_valid_identifier(sym)
1788-
return (isidentifier(sym) && !(sym in keyword_syms)) ||
1789-
(_isoperator(sym) &&
1790-
!(sym in (Symbol("'"), :(::), :?)) &&
1791-
!is_syntactic_operator(sym)
1792-
)
1793-
end
17941685

17951686
# show a normal (non-operator) function call, e.g. f(x, y) or A[z]
17961687
# kw: `=` expressions are parsed with head `kw` in this context

0 commit comments

Comments
 (0)