-
Notifications
You must be signed in to change notification settings - Fork 4
/
Decompile.pq
102 lines (94 loc) · 3.46 KB
/
Decompile.pq
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
(fn) =>
let
// Entry point for routing the calls for various AST node "Kind"s
handleExp = (x) =>
let
kind = x[Kind],
expr = if (kind = "Invocation") then invocationExp(x) else
if (kind = "ElementAccess") then elementAccessExp(x) else
if (kind = "If") then ifExp(x) else
if (kind = "Binary") then binaryExp(x) else
if (kind = "FieldAccess") then fieldAccessExp(x) else
if (kind = "Identifier") then identifierExp(x) else
if (kind = "Constant") then constantExp(x) else
Text.Format("Unkonw Kind: #{0}",{kind})
in
expr,
// "Invocation" node handling
invocationExp = (x) =>
let
f = x[Function],
args = x[Arguments],
funcStr = handleExp(f),
argsStr = Text.Combine(List.Transform(args, each handleExp(_)),",")
in
Text.Format("#{0}(#{1})",{funcStr, argsStr}),
// Get function name from a handle
// TODO: have a peek at #shared first as docs are missleading
functionName = (x) =>
//try getting the name from the associated meta Documentation
try Value.Metadata(Value.Type(x))[Documentation.Name]
otherwise
// or "ResourceExpression"
try Value.ResourceExpression(x)[Name] otherwise "function",
// "If" node handling
ifExp = (x) =>
let
cond = handleExp(x[Condition]),
left = handleExp(x[TrueCase]),
right = handleExp(x[FalseCase])
in
Text.Format("if(#{0}) then #{1} else #{2}", { cond, left, right }),
// "Operator" node handling
operatorExp = (x) =>
let
op =
if (x = "Equals") then "=" else
if (x = "NotEquals") then "!=" else
if (x = "GreaterThan") then ">" else
if (x = "GreaterThanOrEquals") then ">=" else
if (x = "LessThan") then "<" else
if (x = "LessThanOrEquals") then "<=" else
if (x = "And") then "and" else
if (x = "Or") then "or" else
if (x = "Not") then "not" else
if (x = "Add") then "+" else
if (x = "Subtract") then "-" else
if (x = "Multiply") then "*" else
if (x = "Divide") then "/" else
if (x = "Concatenate") then "&" else
x
in
op,
// "Identifier" node handling
identifierExp = (x) => x[Name],
// "Constnt" node handling
constantExp = (x) => x[Value],
// "FieldAccess" node handling
fieldAccessExp = (x) => x[MemberName],
// "ElementAccess" node handling
elementAccessExp = (x) =>
let
refList = x[Collection][Value],
idx = x[Key][Value]
in functionName(refList{idx}),
// Handles node of a "Binary" expression
binaryExp = (x) =>
let
op = operatorExp(x[Operator]),
left = handleExp(x[Left]),
right = handleExp(x[Right]),
format = if (op = "&") then "#{0} & #{2}"
else "#{0} #{1} #{2}"
in
Text.Format(format, {left, op, right}),
// Looping through the Members of a shallow AST and calls expression->text function:handleExp(x)
run = (x)=>
let
members = x[Members]
in
List.Transform(members,each Text.Format("#{0} = #{1}",{_[Name],handleExp(_[Value])})),
AST = Value.ResourceExpression(fn)[Expression][Arguments]{0}[Function][Expression][Expression],
expression = run(AST)
in
expression