From 4f040c35f8c9951285408349bb420ee6c0e23861 Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Wed, 12 Apr 2023 16:38:31 -0400 Subject: [PATCH] generated from Expronicon --- Project.toml | 2 +- src/ExproniconLite.jl | 2 +- src/analysis/compare.jl | 26 ++++++++++----------- src/analysis/cons.jl | 49 +++++++++++++++++++++++---------------- src/analysis/exception.jl | 10 ++++++++ src/analysis/split.jl | 28 +++++++++++----------- test/analysis.jl | 6 ++--- 7 files changed, 71 insertions(+), 52 deletions(-) diff --git a/Project.toml b/Project.toml index efca164..25f633e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ExproniconLite" uuid = "55351af7-c7e9-48d6-89ff-24e801d99491" authors = ["Roger-luo and contributors"] -version = "0.10.1" +version = "0.10.2" [deps] Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" diff --git a/src/ExproniconLite.jl b/src/ExproniconLite.jl index 6148097..91aba69 100644 --- a/src/ExproniconLite.jl +++ b/src/ExproniconLite.jl @@ -23,7 +23,7 @@ end end end - export NoDefault, JLExpr, JLFor, JLIfElse, JLFunction, JLField, JLKwField, JLStruct, JLKwStruct, @expr, @test_expr, compare_expr, AnalysisError, is_function, is_kw_function, is_struct, is_tuple, is_splat, is_ifelse, is_for, is_field, is_field_default, is_datatype_expr, is_matrix_expr, split_function, split_function_head, split_struct, split_struct_name, split_ifelse, uninferrable_typevars, has_symbol, is_literal, is_gensym, alias_gensym, has_kwfn_constructor, has_plain_constructor, guess_type, guess_module, guess_value, Substitute, no_default, prettify, rm_lineinfo, flatten_blocks, name_only, annotations_only, rm_annotations, rm_single_block, rm_nothing, substitute, eval_interp, eval_literal, renumber_gensym, expr_map, nexprs, codegen_ast, codegen_ast_kwfn, codegen_ast_kwfn_plain, codegen_ast_kwfn_infer, codegen_ast_struct, codegen_ast_struct_head, codegen_ast_struct_body, struct_name_plain, struct_name_without_inferable, xtuple, xnamedtuple, xcall, xpush, xgetindex, xfirst, xlast, xprint, xprintln, xmap, xmapreduce, xiterate, print_inline, print_expr, sprint_expr + export NoDefault, JLExpr, JLFor, JLIfElse, JLFunction, JLField, JLKwField, JLStruct, JLKwStruct, @expr, @test_expr, compare_expr, AnalysisError, SyntaxError, is_function, is_kw_function, is_struct, is_tuple, is_splat, is_ifelse, is_for, is_field, is_field_default, is_datatype_expr, is_matrix_expr, split_function, split_function_head, split_struct, split_struct_name, split_ifelse, uninferrable_typevars, has_symbol, is_literal, is_gensym, alias_gensym, has_kwfn_constructor, has_plain_constructor, guess_type, guess_module, guess_value, Substitute, no_default, prettify, rm_lineinfo, flatten_blocks, name_only, annotations_only, rm_annotations, rm_single_block, rm_nothing, substitute, eval_interp, eval_literal, renumber_gensym, expr_map, nexprs, codegen_ast, codegen_ast_kwfn, codegen_ast_kwfn_plain, codegen_ast_kwfn_infer, codegen_ast_struct, codegen_ast_struct_head, codegen_ast_struct_body, struct_name_plain, struct_name_without_inferable, xtuple, xnamedtuple, xcall, xpush, xgetindex, xfirst, xlast, xprint, xprintln, xmap, xmapreduce, xiterate, print_inline, print_expr, sprint_expr #= none:60 =# @static if !(#= none:60 =# @isdefined(eachsplit)) eachsplit(s, pat) = begin split(s, pat) diff --git a/src/analysis/compare.jl b/src/analysis/compare.jl index 3d019d9..923e598 100644 --- a/src/analysis/compare.jl +++ b/src/analysis/compare.jl @@ -95,46 +95,46 @@ $(Expr(:symbolicgoto, Symbol("####final#386#436"))) end end - if var"##387" isa Tuple{LineNumberNode, LineNumberNode} + if var"##387" isa Tuple{TypeVar, TypeVar} if begin var"##390" = var"##387"[1] - var"##390" isa LineNumberNode + var"##390" isa TypeVar end && begin var"##391" = var"##387"[2] - var"##391" isa LineNumberNode + var"##391" isa TypeVar end var"##return#385" = begin + compare_expr(m, lhs.lb, rhs.lb) || return false + compare_expr(m, lhs.ub, rhs.ub) || return false return true end $(Expr(:symbolicgoto, Symbol("####final#386#436"))) end end - if var"##387" isa Tuple{GlobalRef, GlobalRef} + if var"##387" isa Tuple{LineNumberNode, LineNumberNode} if begin var"##392" = var"##387"[1] - var"##392" isa GlobalRef + var"##392" isa LineNumberNode end && begin var"##393" = var"##387"[2] - var"##393" isa GlobalRef + var"##393" isa LineNumberNode end var"##return#385" = begin - return lhs === rhs + return true end $(Expr(:symbolicgoto, Symbol("####final#386#436"))) end end - if var"##387" isa Tuple{TypeVar, TypeVar} + if var"##387" isa Tuple{GlobalRef, GlobalRef} if begin var"##394" = var"##387"[1] - var"##394" isa TypeVar + var"##394" isa GlobalRef end && begin var"##395" = var"##387"[2] - var"##395" isa TypeVar + var"##395" isa GlobalRef end var"##return#385" = begin - compare_expr(m, lhs.lb, rhs.lb) || return false - compare_expr(m, lhs.ub, rhs.ub) || return false - return true + return lhs === rhs end $(Expr(:symbolicgoto, Symbol("####final#386#436"))) end diff --git a/src/analysis/cons.jl b/src/analysis/cons.jl index 7348f6f..7aa4cbf 100644 --- a/src/analysis/cons.jl +++ b/src/analysis/cons.jl @@ -1,25 +1,31 @@ - #= none:1 =# Core.@doc " JLFunction(ex::Expr)\n\nCreate a `JLFunction` object from a Julia function `Expr`.\n\n# Example\n\n```julia\njulia> JLFunction(:(f(x) = 2))\nf(x) = begin\n #= REPL[37]:1 =# \n 2 \nend\n```\n" function JLFunction(ex::Expr) + #= none:1 =# Core.@doc " JLFunction(ex::Expr)\n\nCreate a `JLFunction` object from a Julia function `Expr`.\n\n# Example\n\n```julia\njulia> JLFunction(:(f(x) = 2))\nf(x) = begin\n #= REPL[37]:1 =# \n 2 \nend\n```\n" function JLFunction(ex::Expr; source = nothing) (line, doc, expr) = split_doc(ex) - (head, call, body) = split_function(expr) - (name, args, kw, whereparams, rettype) = split_function_head(call) + if !(isnothing(doc)) + source = line + end + (head, call, body) = split_function(expr; source) + (name, args, kw, whereparams, rettype) = split_function_head(call; source) JLFunction(head, name, args, kw, rettype, whereparams, body, line, doc) end - #= none:23 =# Core.@doc " JLStruct(ex::Expr)\n\nCreate a `JLStruct` object from a Julia struct `Expr`.\n\n# Example\n\n```julia\njulia> JLStruct(:(struct Foo\n x::Int\n end))\nstruct Foo\n #= REPL[38]:2 =#\n x::Int\nend\n```\n" function JLStruct(ex::Expr) + #= none:27 =# Core.@doc " JLStruct(ex::Expr)\n\nCreate a `JLStruct` object from a Julia struct `Expr`.\n\n# Example\n\n```julia\njulia> JLStruct(:(struct Foo\n x::Int\n end))\nstruct Foo\n #= REPL[38]:2 =#\n x::Int\nend\n```\n" function JLStruct(ex::Expr; source = nothing) (line, doc, expr) = split_doc(ex) - (ismutable, typename, typevars, supertype, body) = split_struct(expr) + if !(isnothing(doc)) + source = line + end + (ismutable, typename, typevars, supertype, body) = split_struct(expr; source) (fields, constructors, misc) = (JLField[], JLFunction[], []) - (field_doc, field_line) = (nothing, nothing) + (field_doc, field_source) = (nothing, source) body = flatten_blocks(body) for each = body.args - m = split_field_if_match(typename, each) + m = split_field_if_match(typename, each; source = field_source) if m isa String field_doc = m elseif m isa LineNumberNode - field_line = m + field_source = m elseif m isa NamedTuple - push!(fields, JLField(; m..., doc = field_doc, line = field_line)) - (field_doc, field_line) = (nothing, nothing) + push!(fields, JLField(; m..., doc = field_doc, line = field_source)) + (field_doc, field_source) = (nothing, nothing) elseif m isa JLFunction push!(constructors, m) else @@ -28,22 +34,25 @@ end JLStruct(typename, ismutable, typevars, supertype, fields, constructors, line, doc, misc) end - #= none:67 =# Core.@doc " JLKwStruct(ex::Expr, typealias=nothing)\n\nCreate a `JLKwStruct` from given Julia struct `Expr`, with an option to attach\nan alias to this type name.\n\n# Example\n\n```julia\njulia> JLKwStruct(:(struct Foo\n x::Int = 1\n end))\n#= kw =# struct Foo\n #= REPL[39]:2 =#\n x::Int = 1\nend\n```\n" function JLKwStruct(ex::Expr, typealias = nothing) + #= none:74 =# Core.@doc " JLKwStruct(ex::Expr, typealias=nothing)\n\nCreate a `JLKwStruct` from given Julia struct `Expr`, with an option to attach\nan alias to this type name.\n\n# Example\n\n```julia\njulia> JLKwStruct(:(struct Foo\n x::Int = 1\n end))\n#= kw =# struct Foo\n #= REPL[39]:2 =#\n x::Int = 1\nend\n```\n" function JLKwStruct(ex::Expr, typealias = nothing; source = nothing) (line, doc, expr) = split_doc(ex) - (ismutable, typename, typevars, supertype, body) = split_struct(expr) + if !(isnothing(doc)) + source = line + end + (ismutable, typename, typevars, supertype, body) = split_struct(expr; source) (fields, constructors, misc) = (JLKwField[], JLFunction[], []) - (field_doc, field_line) = (nothing, nothing) + (field_doc, field_source) = (nothing, source) body = flatten_blocks(body) for each = body.args - m = split_field_if_match(typename, each, true) + m = split_field_if_match(typename, each, true; source = field_source) if m isa String field_doc = m elseif m isa LineNumberNode - field_line = m + field_source = m elseif m isa NamedTuple - field = JLKwField(; m..., doc = field_doc, line = field_line) + field = JLKwField(; m..., doc = field_doc, line = field_source) push!(fields, field) - (field_doc, field_line) = (nothing, nothing) + (field_doc, field_source) = (nothing, nothing) elseif m isa JLFunction push!(constructors, m) else @@ -52,12 +61,12 @@ end JLKwStruct(typename, typealias, ismutable, typevars, supertype, fields, constructors, line, doc, misc) end - #= none:111 =# Core.@doc " JLIfElse(ex::Expr)\n\nCreate a `JLIfElse` from given Julia ifelse `Expr`.\n\n# Example\n\n```julia\njulia> ex = :(if foo(x)\n x = 1 + 1\n elseif goo(x)\n y = 1 + 2\n else\n error(\"abc\")\n end)\n:(if foo(x)\n #= REPL[41]:2 =#\n x = 1 + 1\n elseif #= REPL[41]:3 =# goo(x)\n #= REPL[41]:4 =#\n y = 1 + 2\n else\n #= REPL[41]:6 =#\n error(\"abc\")\n end)\n\njulia> JLIfElse(ex)\nif foo(x)\n begin\n #= REPL[41]:2 =# \n x = 1 + 1 \n end\nelseif begin\n #= REPL[41]:3 =# \n goo(x) \nend\n begin\n #= REPL[41]:4 =# \n y = 1 + 2 \n end\nelse\n begin\n #= REPL[41]:6 =# \n error(\"abc\") \n end\nend\n```\n" function JLIfElse(ex::Expr) - ex.head === :if || error("expect an if ... elseif ... else ... end expression") + #= none:121 =# Core.@doc " JLIfElse(ex::Expr)\n\nCreate a `JLIfElse` from given Julia ifelse `Expr`.\n\n# Example\n\n```julia\njulia> ex = :(if foo(x)\n x = 1 + 1\n elseif goo(x)\n y = 1 + 2\n else\n error(\"abc\")\n end)\n:(if foo(x)\n #= REPL[41]:2 =#\n x = 1 + 1\n elseif #= REPL[41]:3 =# goo(x)\n #= REPL[41]:4 =#\n y = 1 + 2\n else\n #= REPL[41]:6 =#\n error(\"abc\")\n end)\n\njulia> JLIfElse(ex)\nif foo(x)\n begin\n #= REPL[41]:2 =# \n x = 1 + 1 \n end\nelseif begin\n #= REPL[41]:3 =# \n goo(x) \nend\n begin\n #= REPL[41]:4 =# \n y = 1 + 2 \n end\nelse\n begin\n #= REPL[41]:6 =# \n error(\"abc\") \n end\nend\n```\n" function JLIfElse(ex::Expr; source = nothing) + ex.head === :if || throw(SyntaxError("expect an if ... elseif ... else ... end expression", source)) (conds, stmts, otherwise) = split_ifelse(ex) return JLIfElse(conds, stmts, otherwise) end - #= none:165 =# Core.@doc " JLFor(ex::Expr)\n\nCreate a `JLFor` from given Julia for loop expression.\n\n# Example\n\n```julia\njulia> ex = @expr for i in 1:10, j in 1:j\n M[i, j] += 1\n end\n:(for i = 1:10, j = 1:j\n #= REPL[3]:2 =#\n M[i, j] += 1\n end)\n\njulia> jl = JLFor(ex)\nfor i in 1 : 10,\n j in 1 : j\n #= loop body =#\n begin\n #= REPL[3]:2 =# \n M[i, j] += 1 \n end\nend\n\njulia> jl.vars\n2-element Vector{Any}:\n :i\n :j\n\njulia> jl.iterators\n2-element Vector{Any}:\n :(1:10)\n :(1:j)\n```\n" function JLFor(ex::Expr) + #= none:177 =# Core.@doc " JLFor(ex::Expr)\n\nCreate a `JLFor` from given Julia for loop expression.\n\n# Example\n\n```julia\njulia> ex = @expr for i in 1:10, j in 1:j\n M[i, j] += 1\n end\n:(for i = 1:10, j = 1:j\n #= REPL[3]:2 =#\n M[i, j] += 1\n end)\n\njulia> jl = JLFor(ex)\nfor i in 1 : 10,\n j in 1 : j\n #= loop body =#\n begin\n #= REPL[3]:2 =# \n M[i, j] += 1 \n end\nend\n\njulia> jl.vars\n2-element Vector{Any}:\n :i\n :j\n\njulia> jl.iterators\n2-element Vector{Any}:\n :(1:10)\n :(1:j)\n```\n" function JLFor(ex::Expr) (vars, itrs, body) = split_forloop(ex) return JLFor(vars, itrs, body) end diff --git a/src/analysis/exception.jl b/src/analysis/exception.jl index bcf9c92..fbdf80f 100644 --- a/src/analysis/exception.jl +++ b/src/analysis/exception.jl @@ -1,4 +1,14 @@ + struct SyntaxError <: Exception + msg::AbstractString + source::Union{Nothing, LineNumberNode} + end + SyntaxError(msg::AbstractString; source = nothing) = begin + SyntaxError(msg, source) + end + function Base.showerror(io::IO, err::SyntaxError) + print(io, "SyntaxError: ", err.msg, " at ", err.source) + end struct AnalysisError <: Exception expect::String got diff --git a/src/analysis/split.jl b/src/analysis/split.jl index 7613f09..d3840ff 100644 --- a/src/analysis/split.jl +++ b/src/analysis/split.jl @@ -125,7 +125,7 @@ var"##return#532" end end - #= none:24 =# Core.@doc " split_function(ex::Expr) -> head, call, body\n\nSplit function head declaration with function body.\n" function split_function(ex::Expr) + #= none:24 =# Core.@doc " split_function(ex::Expr) -> head, call, body\n\nSplit function head declaration with function body.\n" function split_function(ex::Expr; source = nothing) let begin var"##cache#566" = nothing @@ -187,7 +187,7 @@ end begin var"##return#563" = let - anlys_error("function", ex) + throw(SyntaxError("expect a function expr, got $(ex)", source)) end $(Expr(:symbolicgoto, Symbol("####final#564#579"))) end @@ -196,7 +196,7 @@ var"##return#563" end end - #= none:38 =# Core.@doc " split_function_head(ex::Expr) -> name, args, kw, whereparams, rettype\n\nSplit function head to name, arguments, keyword arguments and where parameters.\n" function split_function_head(ex::Expr) + #= none:38 =# Core.@doc " split_function_head(ex::Expr) -> name, args, kw, whereparams, rettype\n\nSplit function head to name, arguments, keyword arguments and where parameters.\n" function split_function_head(ex::Expr; source = nothing) let begin var"##cache#583" = nothing @@ -392,7 +392,7 @@ end begin var"##return#580" = let - anlys_error("function head expr", ex) + throw(SyntaxError("expect a function head, got $(ex)", source)) end $(Expr(:symbolicgoto, Symbol("####final#581#631"))) end @@ -401,7 +401,7 @@ var"##return#580" end end - #= none:63 =# Core.@doc " split_struct_name(ex::Expr) -> name, typevars, supertype\n\nSplit the name, type parameters and supertype definition from `struct`\ndeclaration head.\n" function split_struct_name(#= none:69 =# @nospecialize(ex)) + #= none:63 =# Core.@doc " split_struct_name(ex::Expr) -> name, typevars, supertype\n\nSplit the name, type parameters and supertype definition from `struct`\ndeclaration head.\n" function split_struct_name(#= none:69 =# @nospecialize(ex); source = nothing) return let begin var"##cache#635" = nothing @@ -487,7 +487,7 @@ end begin var"##return#632" = let - anlys_error("struct", ex) + throw(SyntaxError("expect struct got $(ex)", source)) end $(Expr(:symbolicgoto, Symbol("####final#633#653"))) end @@ -496,9 +496,9 @@ var"##return#632" end end - #= none:79 =# Core.@doc " split_struct(ex::Expr) -> ismutable, name, typevars, supertype, body\n\nSplit struct definition head and body.\n" function split_struct(ex::Expr) - ex.head === :struct || error("expect a struct expr, got $(ex)") - (name, typevars, supertype) = split_struct_name(ex.args[2]) + #= none:79 =# Core.@doc " split_struct(ex::Expr) -> ismutable, name, typevars, supertype, body\n\nSplit struct definition head and body.\n" function split_struct(ex::Expr; source = nothing) + ex.head === :struct || throw(SyntaxError("expect a struct expr, got $(ex)", source)) + (name, typevars, supertype) = split_struct_name(ex.args[2]; source) body = ex.args[3] return (ex.args[1], name, typevars, supertype, body) end @@ -562,7 +562,7 @@ end return uninferrable end - #= none:161 =# Core.@doc " split_field_if_match(typename::Symbol, expr, default::Bool=false)\n\nSplit the field definition if it matches the given type name.\nReturns `NamedTuple` with `name`, `type`, `default` and `isconst` fields\nif it matches, otherwise return `nothing`.\n" function split_field_if_match(typename::Symbol, expr, default::Bool = false) + #= none:161 =# Core.@doc " split_field_if_match(typename::Symbol, expr, default::Bool=false)\n\nSplit the field definition if it matches the given type name.\nReturns `NamedTuple` with `name`, `type`, `default` and `isconst` fields\nif it matches, otherwise return `nothing`.\n" function split_field_if_match(typename::Symbol, expr, default::Bool = false; source = nothing) begin begin var"##cache#657" = nothing @@ -621,7 +621,7 @@ name = var"##668" var"##return#654" = begin default && return (; name, type, isconst = true, default = value) - throw(ArgumentError("default value syntax is not allowed")) + throw(SyntaxError("default value syntax is not allowed", source)) end $(Expr(:symbolicgoto, Symbol("####final#655#707"))) end @@ -657,7 +657,7 @@ name = var"##677" var"##return#654" = begin default && return (; name, type = Any, isconst = true, default = value) - throw(ArgumentError("default value syntax is not allowed")) + throw(SyntaxError("default value syntax is not allowed", source)) end $(Expr(:symbolicgoto, Symbol("####final#655#707"))) end @@ -695,7 +695,7 @@ name = var"##685" var"##return#654" = begin default && return (; name, type, isconst = false, default = value) - throw(ArgumentError("default value syntax is not allowed")) + throw(SyntaxError("default value syntax is not allowed", source)) end $(Expr(:symbolicgoto, Symbol("####final#655#707"))) end @@ -716,7 +716,7 @@ name = var"##690" var"##return#654" = begin default && return (; name, type = Any, isconst = false, default = value) - throw(ArgumentError("default value syntax is not allowed")) + throw(SyntaxError("default value syntax is not allowed", source)) end $(Expr(:symbolicgoto, Symbol("####final#655#707"))) end diff --git a/test/analysis.jl b/test/analysis.jl index ba635b7..4b9cff5 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -112,9 +112,9 @@ end ex = :(struct Foo end) - #= none:134 =# @test_throws AnalysisError JLFunction(ex) + #= none:134 =# @test_throws SyntaxError JLFunction(ex) ex = :(#= none:135 =# @foo(2, 3)) - #= none:136 =# @test_throws AnalysisError split_function_head(ex) + #= none:136 =# @test_throws SyntaxError split_function_head(ex) ex = :(Foo(; a = 1) = begin new(a) end) @@ -181,7 +181,7 @@ #= none:208 =# @test (ast.args[4]).head === :struct #= none:209 =# @test is_function(((ast.args[4]).args[end]).args[end - 1]) println(jlstruct) - #= none:212 =# @test_throws AnalysisError split_struct_name(:(function Foo end)) + #= none:212 =# @test_throws SyntaxError split_struct_name(:(function Foo end)) end #= none:215 =# @testset "JLKwStruct" begin def = #= none:216 =# @expr(JLKwStruct, struct Trait