-
Notifications
You must be signed in to change notification settings - Fork 15
/
AST_translation_tables.jl
231 lines (192 loc) · 8.11 KB
/
AST_translation_tables.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
## Things that can't be loaded twice.g
# Some instances of data structures
## Symbol correspondence/translation between Julia and Symata
# This should be separated better. Some symbols are translated
# only on analyzing the ast, others, on both input and output.
# Fix. We delete the keys we don't want (unicode) from the reverse translation.
#### Input,Output translation table.
# These translations are made when encountered in the AST and on printing.
# A reversed dict is constructed for output.
# Excepted are the unicode characters. They are merged into the input dict.
# But, they are held in a separate table for output, so that unicode
# output can be disabled.
# Idea, but not implemented:
# We could use a.b for contexts, modules. In Mma
# a . b == a.b == Dot[a,b], matrix and vector multiplication.
# a`b is symbol b in context a. a .* b is illegal in Mma, but a .* b is legal syntax in Julia
# So: in Symata a.b for contexts, and a .* b for matrix multiplication
# We can use $ for (Symata) Function, but the translation to compound expression is broken
# We can use -> for (Symata) Function. This seems to work
## Symbols not yet in use
## .\
const JTOMSYM =
Dict(
:(=) => :Set,
:(:=) => :SetDelayed,
:(^=) => :UpSet,
:+ => :Plus,
:- => :Minus,
:* => :Times,
:⋅ => :Dot,
:^ => :Power,
:(*=) => :TimesBy,
:(+=) => :AddTo,
# $ is good for Function below, but we might want it for interpolation instead
# No, it does not interfere with interpolation, but it still wraps args in Comound expression. dont know why
:(->) => :Function,
:$ => :Function, # $(1+~2) --> Function(Plus(1,Slot(2))), but we don't do anything yet with this
:~ => :Slot, # we need to translate lone ~ , ie Slot into Slot(1)
:(=>) => :Rule, # Mma uses ->. We use => because it has a higher precedence than ->, which is what we want.
# :(->) => :RuleDelayed, # Mma uses :>. Julia parser does not allow this
:(.>) => :RuleDelayed, # Mma uses :>. Julia parser does not allow this. .> has better precedence and parsing than ->
:(./) => :ReplaceAll, # Mma has /. for this !! But, /. is not legal Julia syntax
:(.//) => :ReplaceRepeated,
:(%) => :Map,
:(.%) => :Apply,
# :(:) => :Span, # in v0.7, colon has become a call. We discriminate meaning by context
:(&=) => :UpSetDelayed, # This is available, at least. Not sure we want to take it.
:... => :... , # We still need to decide what to do with this. Maybe evaluate the args and Apply Sequence
:.. => :..,
:! => :Not,
:&& => :And,
:|| => :Or,
:| => :Alternatives,
:(...) => :Repeated
)
const JTOMSYM_ONEWAY =
Dict(
:vcat => :List,
:vect => :List,
:ref => :Part,
:cell1d => :List, # curly brackets, but deprecated by julia
:comparison => :Comparison,
)
# FIXME NB Alternatives: This is nary, but not Flat. So we need to parse
# a | b | c as Alternatives(a,b,c) rather than nested Alternatives as we do now.
# (a | b) | c is nested, and is not flattend.
# Other operators, such as Times are nary but Flat, so the flattening happens during the
# evaluations sequence.
# These symbols are unconditionally translated on input
# This is almost exactly the Dict unicode_translation. Maybe we can refactor.
const INSYMTRANS = Dict( :⇒ => :(=>),
:π => :Pi,
:≥ => :(>=),
:≤ => :(<=),
:γ => :EulerGamma,
:Γ => :Gamma,
:𝕖 => :E,
:𝕚 => :I,
:∞ => :Infinity,
:≠ => :!=,
:∈ => :Element
)
# Input translation. Output translation if unicode is enabled
const unicode_translation = Dict{Symbol,Symbol}(:π => :Pi,
:γ => :EulerGamma,
:∞ => :Infinity,
:Γ => :Gamma,
:𝕚 => :I,
:≥ => :>=,
:≤ => :<=,
:≠ => :!=,
:𝕖 => :E,
:⇒ => :(=>),
:→ => :Function,
:∈ => :Element
)
const comparison_translation = Dict(
:(==) => :Equal,
:(!=) => :Unequal,
:(>) => :Greater,
:(<) => :Less,
:(>=) => :GreaterEqual,
:(<=) => :LessEqual,
:(===) => :SameQ,
:(!==) => :UnsameQ
)
const inverse_comparison_translation = Dict{Symbol,Symbol}()
for x in comparison_translation
inverse_comparison_translation[x[2]] = x[1]
end
# Output. Reverse dict for printing if unicode printing is enabled
const unicode_output = Dict{Symbol,Symbol}()
for (k,v) in unicode_translation unicode_output[v] = k end
# Reverse dict of ascii symbols for printing
const MTOJSYM = Dict{Symbol,Symbol}()
for (k,v) in JTOMSYM MTOJSYM[v] = k end
# Finally, add the unicode symbols to the input translation table.
merge!(JTOMSYM, unicode_translation)
merge!(JTOMSYM, JTOMSYM_ONEWAY)
# This is only used for output. (Can't we detect it with the others on input ?)
MTOJSYM[:Span] = :(:)
merge!(MTOJSYM, inverse_comparison_translation)
function jtomsym(x::Symbol)
check_autoload(x) # trigger autoload of Symata language code
if haskey(JTOMSYM,x)
return JTOMSYM[x]
end
return x
end
jtomsym(x) = extomx(x)
function mtojsym(x::Symbol)
# For output, reverse the rewrites done by preprocessing the input string befor parsing
if haskey(REVERSE_PREPROCESS_SYMBOL_TRANSLATION,x) # .> --> :> for output
x = REVERSE_PREPROCESS_SYMBOL_TRANSLATION[x] # => --> ->
end
if haskey(MTOJSYM,x)
return MTOJSYM[x]
end
return x
end
# Non-Symbol Heads translate to themselves
mtojsym(x) = x
# These will not be translated back to Julia expression symbol on printing
# TODO. choose tuple or block, or both ?
# One unusual occurance of :block is filtered before we get here
# A compound expression is denoted by tuple () or by begin end.
# We could possible used tuple for something else.
for (k,v) = ( (:tuple,:CompoundExpression), (:block,:CompoundExpression), (:dict, :List), (:parameters, :TestExpression) )
JTOMSYM[k] = v
end
#### Operator type: infix, prefix, postfix
const OPTYPE = Dict{Symbol,Symbol}()
for op in (:(=), :(:=), :(=>), :Rule , :RuleDelayed, :Power, :(.>),
:Set, :SetDelayed, :UpSet, :(*=), :(+=), :→, :(->), :Function,
:TimesBy, :AddTo # , :Element
) # need :Set here
OPTYPE[op] = :binary
end
for op in keys(inverse_comparison_translation)
OPTYPE[op] = :binary
end
for op in (:Plus, :Times, :Dot, :Span, :And, :Or, :Alternatives)
OPTYPE[op] = :infix
end
# Nonsymbolic Heads, Integer, etc. assume they are prefix ops
getoptype(x) = :prefix
# function getoptype(x::Mxpr)
# println("getting opt type for ", mhead(x), " args ", margs(x))
# res = getoptype(mhead(x))
# println("Resutt is $res")
# res
# end
function getoptype(x::Symbol)
if haskey(OPTYPE,x)
return OPTYPE[x]
end
return :prefix
end
#### Comparison symbols
# This is only used in AST_tranlation.jl to make a Comparison Mxpr.
const COMPARISONSYMBOLS = Dict{Symbol,Bool}()
for op in ( :(==), :(<), :(>), :(>=), :(<=), :(===),
:(!=), :(!==), :(<:))
COMPARISONSYMBOLS[op] = true
end
function is_comparison_symbol(x::Symbol)
if haskey(COMPARISONSYMBOLS,x)
return true
end
return false
end
is_comparison_symbol(x) = false