Skip to content

Commit f4db9ce

Browse files
authored
Merge pull request #182 from JuliaLang/c42f/julia-1.0-support
Support for running JuliaSyntax on Julia 1.0
2 parents bb1265e + 50f4e6a commit f4db9ce

File tree

13 files changed

+119
-41
lines changed

13 files changed

+119
-41
lines changed

.github/workflows/CI.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
version:
16+
- '1.0'
17+
- '1.1'
18+
- '1.2'
19+
- '1.3'
20+
- '1.4'
21+
- '1.5'
1622
- '1.6'
23+
- '1.7'
1724
- '1'
1825
- 'nightly'
1926
os:
@@ -22,6 +29,26 @@ jobs:
2229
- windows-latest
2330
arch:
2431
- x64
32+
exclude:
33+
# Test all OS's on
34+
# - 1.0
35+
# - 1.6
36+
# - 1
37+
# - nightly
38+
# but remove some configurations from the build matrix to reduce CI time.
39+
# See https://github.com/marketplace/actions/setup-julia-environment
40+
- {os: 'macOS-latest', version: '1.1'}
41+
- {os: 'macOS-latest', version: '1.2'}
42+
- {os: 'macOS-latest', version: '1.3'}
43+
- {os: 'macOS-latest', version: '1.4'}
44+
- {os: 'macOS-latest', version: '1.5'}
45+
- {os: 'macOS-latest', version: '1.7'}
46+
- {os: 'windows-latest', version: '1.1'}
47+
- {os: 'windows-latest', version: '1.2'}
48+
- {os: 'windows-latest', version: '1.3'}
49+
- {os: 'windows-latest', version: '1.4'}
50+
- {os: 'windows-latest', version: '1.5'}
51+
- {os: 'windows-latest', version: '1.7'}
2552
steps:
2653
- uses: actions/checkout@v2
2754
- uses: julia-actions/setup-julia@v1

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ authors = ["Chris Foster <[email protected]> and contributors"]
44
version = "0.2.0"
55

66
[compat]
7-
julia = "1.6"
7+
julia = "1.0"
88

99
[deps]
1010

src/expr.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true,
4545
Symbol("@big_str")
4646
return Expr(:macrocall, GlobalRef(Core, macname), nothing, str)
4747
elseif kind(node) == K"core_@doc"
48-
return GlobalRef(Core, :var"@doc")
48+
return GlobalRef(Core, Symbol("@doc"))
4949
elseif kind(node) == K"core_@cmd"
50-
return GlobalRef(Core, :var"@cmd")
50+
return GlobalRef(Core, Symbol("@cmd"))
5151
elseif kind(node) == K"MacroName" && val === Symbol("@.")
5252
return Symbol("@__dot__")
5353
else

src/hooks.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,21 @@ end
237237
function _fl_parse_hook(code, filename, lineno, offset, options)
238238
@static if VERSION >= v"1.8.0-DEV.1370" # https://github.com/JuliaLang/julia/pull/43876
239239
return Core.Compiler.fl_parse(code, filename, lineno, offset, options)
240-
else
240+
elseif VERSION >= v"1.6"
241241
return Core.Compiler.fl_parse(code, filename, offset, options)
242+
else
243+
if options === :all
244+
ex = Base.parse_input_line(String(code), filename=filename, depwarn=false)
245+
if !Meta.isexpr(ex, :toplevel)
246+
ex = Expr(:toplevel, ex)
247+
end
248+
return ex, sizeof(code)
249+
elseif options === :statement || options == :atom
250+
ex, pos = Meta.parse(code, offset+1, greedy=options==:statement, raise=false)
251+
return ex, pos-1
252+
else
253+
error("Unknown parse options $options")
254+
end
242255
end
243256
end
244257

@@ -248,7 +261,7 @@ end
248261
# FIXME: Improve this in Base somehow?
249262
Base.Meta.ParseError(e::JuliaSyntax.ParseError) = e
250263

251-
const _default_parser = Core._parse
264+
const _default_parser = VERSION < v"1.6" ? nothing : Core._parse
252265

253266
"""
254267
enable_in_core!([enable=true; freeze_world_age, debug_filename])
@@ -266,6 +279,9 @@ Keyword arguments:
266279
"""
267280
function enable_in_core!(enable=true; freeze_world_age = true,
268281
debug_filename = get(ENV, "JULIA_SYNTAX_DEBUG_FILE", nothing))
282+
if VERSION < v"1.6"
283+
error("Cannot use JuliaSyntax as the main Julia parser in Julia version $VERSION < 1.6")
284+
end
269285
_parser_world_age[] = freeze_world_age ? Base.get_world_counter() : _latest_world
270286
if enable && !isnothing(debug_filename)
271287
_debug_log[] = open(debug_filename, "w")

src/source_files.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ function source_line_range(source::SourceFile, byte_index;
6565
end
6666

6767
function source_location(::Type{LineNumberNode}, source::SourceFile, byte_index)
68-
LineNumberNode(source_line(source, byte_index), source.filename)
68+
LineNumberNode(source_line(source, byte_index),
69+
isnothing(source.filename) ? nothing : Symbol(source.filename))
6970
end
7071

7172
function Base.show(io::IO, ::MIME"text/plain", source::SourceFile)

src/utils.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
# Compatibility hacks for older Julia versions
2+
if VERSION < v"1.1"
3+
isnothing(x) = x === nothing
4+
end
5+
if VERSION < v"1.4"
6+
function only(x::AbstractVector)
7+
if length(x) != 1
8+
error("Collection must contain exactly 1 element")
9+
end
10+
return x[1]
11+
end
12+
end
13+
if VERSION < v"1.5"
14+
import Base.peek
15+
end
16+
17+
#--------------------------------------------------
18+
#
119
# Internal error, used as assertion failure for cases we expect can't happen.
220
@noinline function internal_error(strs...)
321
error("Internal error: ", strs...)

src/value_parsing.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ end
122122
@inline function _unsafe_parse_float(::Type{Float64}, ptr, strsize)
123123
Libc.errno(0)
124124
endptr = Ref{Ptr{UInt8}}(C_NULL)
125-
x = @ccall jl_strtod_c(ptr::Ptr{UInt8}, endptr::Ptr{Ptr{UInt8}})::Cdouble
125+
x = ccall(:jl_strtod_c, Cdouble, (Ptr{UInt8}, Ptr{Ptr{UInt8}}), ptr, endptr)
126126
@check endptr[] == ptr + strsize
127127
status = :ok
128128
if Libc.errno() == Libc.ERANGE
@@ -155,13 +155,13 @@ end
155155
# strtof seems buggy on windows and doesn't set ERANGE correctly on
156156
# overflow. See also
157157
# https://github.com/JuliaLang/julia/issues/46544
158-
x = Float32(@ccall jl_strtod_c(ptr::Ptr{UInt8}, endptr::Ptr{Ptr{UInt8}})::Cdouble)
158+
x = Float32(ccall(:jl_strtod_c, Cdouble, (Ptr{UInt8}, Ptr{Ptr{UInt8}}), ptr, endptr))
159159
if isinf(x)
160160
status = :overflow
161161
# Underflow not detected, but that will only be a warning elsewhere.
162162
end
163163
else
164-
x = @ccall jl_strtof_c(ptr::Ptr{UInt8}, endptr::Ptr{Ptr{UInt8}})::Cfloat
164+
x = ccall(:jl_strtof_c, Cfloat, (Ptr{UInt8}, Ptr{Ptr{UInt8}}), ptr, endptr)
165165
end
166166
@check endptr[] == ptr + strsize
167167
if Libc.errno() == Libc.ERANGE

test/parse_packages.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Full-scale parsing tests of JuliaSyntax itself, Julia Base, etc.
22

3+
juliasyntax_dir = joinpath(@__DIR__, "..")
34
@testset "Parse JuliaSyntax" begin
4-
pkgdir = joinpath(@__DIR__, "..")
5-
test_parse_all_in_path(joinpath(pkgdir, "src"))
6-
test_parse_all_in_path(joinpath(pkgdir, "test"))
5+
test_parse_all_in_path(joinpath(juliasyntax_dir, "src"))
6+
end
7+
@testset "Parse JuliaSyntax tests" begin
8+
test_parse_all_in_path(joinpath(juliasyntax_dir, "test"))
79
end
810

911
base_path = let

test/parser_api.jl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@
8282
end
8383

8484
@testset "error/warning handling" begin
85-
# ignore_warnings
86-
parse_sexpr(s;kws...) = sprint(show, MIME("text/x.sexpression"), parse(SyntaxNode, s; kws...))
87-
@test_throws JuliaSyntax.ParseError parse_sexpr("try finally catch ex end")
88-
@test parse_sexpr("try finally catch ex end", ignore_warnings=true) ==
85+
parseshow(s;kws...) = sprint(show, MIME("text/x.sexpression"), parse(SyntaxNode, s; kws...))
86+
@test_throws JuliaSyntax.ParseError parseshow("try finally catch ex end")
87+
@test parseshow("try finally catch ex end", ignore_warnings=true) ==
8988
"(try_finally_catch (block) false false false (block) ex (block))"
9089
# ignore_errors
91-
@test_throws JuliaSyntax.ParseError parse_sexpr("[a; b, c]")
92-
@test_throws JuliaSyntax.ParseError parse_sexpr("[a; b, c]", ignore_warnings=true)
93-
@test parse_sexpr("[a; b, c]", ignore_errors=true) == "(vcat a b (error-t) c)"
90+
@test_throws JuliaSyntax.ParseError parseshow("[a; b, c]")
91+
@test_throws JuliaSyntax.ParseError parseshow("[a; b, c]", ignore_warnings=true)
92+
@test parseshow("[a; b, c]", ignore_errors=true) == "(vcat a b (error-t) c)"
9493
end
9594
end

test/runtests.jl

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,28 @@ using JuliaSyntax: GreenNode, SyntaxNode,
77
flags, EMPTY_FLAGS, TRIVIA_FLAG, INFIX_FLAG,
88
children, child, setchild!, SyntaxHead
99

10+
include("test_utils.jl")
11+
# Tests for the test_utils go here to allow the utils to be included on their
12+
# own without invoking the tests.
13+
@testset "Test tools" begin
14+
@test exprs_roughly_equal(Expr(:global, :x, :y),
15+
Expr(:global, Expr(:tuple, :x, :y)))
16+
@test exprs_roughly_equal(Expr(:local, :x, :y),
17+
Expr(:local, Expr(:tuple, :x, :y)))
18+
@test exprs_roughly_equal(1.5,
19+
Expr(:call, :*, 1.5, :f))
20+
@test exprs_roughly_equal(1.5,
21+
Expr(:call, :*, 1.5, :f0))
22+
@test exprs_roughly_equal(Expr(:do, Expr(:macrocall, Symbol("@f"), LineNumberNode(1), Expr(:kw, :a, 1)),
23+
Expr(:->, Expr(:tuple), Expr(:block, LineNumberNode(1)))),
24+
Expr(:do, Expr(:macrocall, Symbol("@f"), LineNumberNode(1), Expr(:(=), :a, 1)),
25+
Expr(:->, Expr(:tuple), Expr(:block, LineNumberNode(1)))))
26+
end
27+
1028
@testset "Tokenize" begin
1129
include("tokenize.jl")
1230
end
1331

14-
include("test_utils.jl")
1532
include("parse_stream.jl")
1633
include("parser.jl")
1734
include("diagnostics.jl")
@@ -20,7 +37,13 @@ include("expr.jl")
2037
@testset "Parsing literals from strings" begin
2138
include("value_parsing.jl")
2239
end
23-
include("hooks.jl")
24-
include("parse_packages.jl")
2540
include("source_files.jl")
2641

42+
if VERSION >= v"1.6"
43+
# Tests restricted to 1.6+ due to
44+
# * Core._parse hook doesn't exist on v1.5 and lower
45+
# * Reference parser bugs which would need workarounds for package parse comparisons
46+
include("hooks.jl")
47+
include("parse_packages.jl")
48+
end
49+

0 commit comments

Comments
 (0)