-
Notifications
You must be signed in to change notification settings - Fork 17
/
parse.jl
130 lines (105 loc) · 2.73 KB
/
parse.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
module Parsers
using Base.Meta
import Base.push!
export parsefile, defs, funcs, recurse,
MetaCollector, FuncCollector, AbstractCollector,
walk, inexpr, findfunc, findassign, replacevar,
postwalk, prewalk, replace, inexpr
include("macrotools.jl")
include("findfunc.jl")
""" parsefile(path)
read in a julia source file and parse it.
Note: If the top level is not a simple expression or module definition the file is wrapped in a Module named modprefix.
"""
function parsefile(path, modprefix="Modeling")
s = read(path, String)
# open(path) do fp
# s = read(String, fp)
# end
try
expr = Base.Meta.parse(s)
return expr
catch
s = "module $modprefix\n$s \nend #module $modprefix"
expr = Base.Meta.parse(s)
return expr
end
end
""" AbstractCollector
subtypes of AbstractCollector support extracting and collecting information
from input sources.
"""
abstract type AbstractCollector end
""" FuncCollector{T} <: AbstractCollector
collects function definitions and names
"""
struct FuncCollector{T} <: AbstractCollector
defs::T
end
function push!(fc::AbstractCollector, expr::LineNumberNode)
return nothing
end
function push!(fc::FuncCollector, expr::Expr)
if expr.head == :function
push!(fc.defs, expr.args[1] => expr.args[2])
end
end
""" MetaCollector{T,U,V,W} <: AbstractCollector
collects multiple pieces of information such as
- exprs: expressions
- fc: functions
- vc: variable assignments
- modc: module imports
"""
struct MetaCollector{T,U,V,W} <: AbstractCollector
exprs::V
fc::T
vc::U
modc::W
end
function push!(mc::MetaCollector, expr::Expr)
push!(mc.exprs, expr)
push!(mc.fc, expr)
if expr.head == :(=)
@debug "pushing into vc" expr=expr
push!(mc.vc, expr.args[1]=>expr.args[2])
elseif expr.head == :using
push!(mc.modc, expr.args[1].args)
else
@info "unknown expr type for metacollector"
@show expr
end
end
""" funcs(body)
collect the function definitions from a module expression.
"""
function funcs(body)
fs = FuncCollector([])
for subexpr in body
push!(fs, subexpr)
end
return fs
end
""" defs(body)
collect the function definitions and variable assignments from a module expression.
"""
function defs(body)
# fs = funcs(body)
mc = MetaCollector(Any[], FuncCollector([]), Any[], Any[])
for expr in body
push!(mc, expr)
end
return mc
end
function recurse(mc::AbstractCollector)
subdefs = Any[]
funcdefs = mc.fc.defs
@show funcdefs
for def in funcdefs
funcname = def[1]
funcquote = def[2]
push!(subdefs, funcname=>defs(funcquote.args))
end
return subdefs
end
end