@@ -65,16 +65,78 @@ type clause struct {
65
65
66
66
func compileClause (head Term , body Term , env * Env ) (clause , error ) {
67
67
var c clause
68
+ var goals []Term
69
+
70
+ head , goals = desugar (head , goals )
71
+ body , goals = desugar (body , goals )
72
+
73
+ if body != nil {
74
+ goals = append (goals , body )
75
+ }
76
+ if len (goals ) > 0 {
77
+ body = seq (atomComma , goals ... )
78
+ }
79
+
68
80
c .compileHead (head , env )
81
+
69
82
if body != nil {
70
83
if err := c .compileBody (body , env ); err != nil {
71
84
return c , typeError (validTypeCallable , body , env )
72
85
}
73
86
}
74
- c .bytecode = append (c .bytecode , instruction {opcode : OpExit })
87
+
88
+ c .emit (instruction {opcode : OpExit })
75
89
return c , nil
76
90
}
77
91
92
+ func desugar (term Term , acc []Term ) (Term , []Term ) {
93
+ switch t := term .(type ) {
94
+ case charList , codeList :
95
+ return t , acc
96
+ case list :
97
+ l := make (list , len (t ))
98
+ for i , e := range t {
99
+ l [i ], acc = desugar (e , acc )
100
+ }
101
+ return l , acc
102
+ case * partial :
103
+ c , acc := desugar (t .Compound , acc )
104
+ tail , acc := desugar (* t .tail , acc )
105
+ return & partial {
106
+ Compound : c .(Compound ),
107
+ tail : & tail ,
108
+ }, acc
109
+ case Compound :
110
+ if t .Functor () == atomSpecialDot && t .Arity () == 2 {
111
+ tempV := NewVariable ()
112
+ lhs , acc := desugar (t .Arg (0 ), acc )
113
+ rhs , acc := desugar (t .Arg (1 ), acc )
114
+
115
+ return tempV , append (acc , atomDot .Apply (lhs , rhs , tempV ))
116
+ }
117
+
118
+ c := compound {
119
+ functor : t .Functor (),
120
+ args : make ([]Term , t .Arity ()),
121
+ }
122
+ for i := 0 ; i < t .Arity (); i ++ {
123
+ c .args [i ], acc = desugar (t .Arg (i ), acc )
124
+ }
125
+
126
+ if _ , ok := t .(Dict ); ok {
127
+ return & dict {c }, acc
128
+ }
129
+
130
+ return & c , acc
131
+ default :
132
+ return t , acc
133
+ }
134
+ }
135
+
136
+ func (c * clause ) emit (i instruction ) {
137
+ c .bytecode = append (c .bytecode , i )
138
+ }
139
+
78
140
func (c * clause ) compileHead (head Term , env * Env ) {
79
141
switch head := env .Resolve (head ).(type ) {
80
142
case Atom :
@@ -88,7 +150,7 @@ func (c *clause) compileHead(head Term, env *Env) {
88
150
}
89
151
90
152
func (c * clause ) compileBody (body Term , env * Env ) error {
91
- c .bytecode = append ( c . bytecode , instruction {opcode : OpEnter })
153
+ c .emit ( instruction {opcode : OpEnter })
92
154
iter := seqIterator {Seq : body , Env : env }
93
155
for iter .Next () {
94
156
if err := c .compilePred (iter .Current (), env ); err != nil {
@@ -107,16 +169,16 @@ func (c *clause) compilePred(p Term, env *Env) error {
107
169
case Atom :
108
170
switch p {
109
171
case atomCut :
110
- c .bytecode = append ( c . bytecode , instruction {opcode : OpCut })
172
+ c .emit ( instruction {opcode : OpCut })
111
173
return nil
112
174
}
113
- c .bytecode = append ( c . bytecode , instruction {opcode : OpCall , operand : procedureIndicator {name : p , arity : 0 }})
175
+ c .emit ( instruction {opcode : OpCall , operand : procedureIndicator {name : p , arity : 0 }})
114
176
return nil
115
177
case Compound :
116
178
for i := 0 ; i < p .Arity (); i ++ {
117
179
c .compileBodyArg (p .Arg (i ), env )
118
180
}
119
- c .bytecode = append ( c . bytecode , instruction {opcode : OpCall , operand : procedureIndicator {name : p .Functor (), arity : Integer (p .Arity ())}})
181
+ c .emit ( instruction {opcode : OpCall , operand : procedureIndicator {name : p .Functor (), arity : Integer (p .Arity ())}})
120
182
return nil
121
183
default :
122
184
return errNotCallable
@@ -126,67 +188,84 @@ func (c *clause) compilePred(p Term, env *Env) error {
126
188
func (c * clause ) compileHeadArg (a Term , env * Env ) {
127
189
switch a := env .Resolve (a ).(type ) {
128
190
case Variable :
129
- c .bytecode = append ( c . bytecode , instruction {opcode : OpGetVar , operand : c .varOffset (a )})
191
+ c .emit ( instruction {opcode : OpGetVar , operand : c .varOffset (a )})
130
192
case charList , codeList : // Treat them as if they're atomic.
131
- c .bytecode = append ( c . bytecode , instruction {opcode : OpGetConst , operand : a })
193
+ c .emit ( instruction {opcode : OpGetConst , operand : a })
132
194
case list :
133
- c .bytecode = append ( c . bytecode , instruction {opcode : OpGetList , operand : Integer (len (a ))})
195
+ c .emit ( instruction {opcode : OpGetList , operand : Integer (len (a ))})
134
196
for _ , arg := range a {
135
197
c .compileHeadArg (arg , env )
136
198
}
137
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPop })
199
+ c .emit ( instruction {opcode : OpPop })
138
200
case * partial :
139
201
prefix := a .Compound .(list )
140
- c .bytecode = append ( c . bytecode , instruction {opcode : OpGetPartial , operand : Integer (len (prefix ))})
202
+ c .emit ( instruction {opcode : OpGetPartial , operand : Integer (len (prefix ))})
141
203
c .compileHeadArg (* a .tail , env )
142
204
for _ , arg := range prefix {
143
205
c .compileHeadArg (arg , env )
144
206
}
145
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPop })
207
+ c .emit ( instruction {opcode : OpPop })
146
208
case Compound :
147
- c .bytecode = append (c .bytecode , instruction {opcode : OpGetFunctor , operand : procedureIndicator {name : a .Functor (), arity : Integer (a .Arity ())}})
209
+ switch a .(type ) {
210
+ case Dict :
211
+ c .emit (instruction {opcode : OpGetDict , operand : Integer (a .Arity ())})
212
+ default :
213
+ c .emit (instruction {opcode : OpGetFunctor , operand : procedureIndicator {name : a .Functor (), arity : Integer (a .Arity ())}})
214
+ }
215
+
148
216
for i := 0 ; i < a .Arity (); i ++ {
149
217
c .compileHeadArg (a .Arg (i ), env )
150
218
}
151
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPop })
219
+ c .emit ( instruction {opcode : OpPop })
152
220
default :
153
- c .bytecode = append ( c . bytecode , instruction {opcode : OpGetConst , operand : a })
221
+ c .emit ( instruction {opcode : OpGetConst , operand : a })
154
222
}
155
223
}
156
224
157
225
func (c * clause ) compileBodyArg (a Term , env * Env ) {
158
226
switch a := env .Resolve (a ).(type ) {
159
227
case Variable :
160
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPutVar , operand : c .varOffset (a )})
228
+ c .emit ( instruction {opcode : OpPutVar , operand : c .varOffset (a )})
161
229
case charList , codeList : // Treat them as if they're atomic.
162
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPutConst , operand : a })
230
+ c .emit ( instruction {opcode : OpPutConst , operand : a })
163
231
case list :
164
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPutList , operand : Integer (len (a ))})
232
+ c .emit ( instruction {opcode : OpPutList , operand : Integer (len (a ))})
165
233
for _ , arg := range a {
166
234
c .compileBodyArg (arg , env )
167
235
}
168
- c .bytecode = append (c .bytecode , instruction {opcode : OpPop })
236
+ c .emit (instruction {opcode : OpPop })
237
+ case Dict :
238
+ c .emit (instruction {opcode : OpPutDict , operand : Integer (a .Arity ())})
239
+ for i := 0 ; i < a .Arity (); i ++ {
240
+ c .compileBodyArg (a .Arg (i ), env )
241
+ }
242
+ c .emit (instruction {opcode : OpPop })
169
243
case * partial :
170
244
var l int
171
245
iter := ListIterator {List : a .Compound }
172
246
for iter .Next () {
173
247
l ++
174
248
}
175
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPutPartial , operand : Integer (l )})
249
+ c .emit ( instruction {opcode : OpPutPartial , operand : Integer (l )})
176
250
c .compileBodyArg (* a .tail , env )
177
251
iter = ListIterator {List : a .Compound }
178
252
for iter .Next () {
179
253
c .compileBodyArg (iter .Current (), env )
180
254
}
181
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPop })
255
+ c .emit ( instruction {opcode : OpPop })
182
256
case Compound :
183
- c .bytecode = append (c .bytecode , instruction {opcode : OpPutFunctor , operand : procedureIndicator {name : a .Functor (), arity : Integer (a .Arity ())}})
257
+ switch a .(type ) {
258
+ case Dict :
259
+ c .emit (instruction {opcode : OpPutDict , operand : Integer (a .Arity ())})
260
+ default :
261
+ c .emit (instruction {opcode : OpPutFunctor , operand : procedureIndicator {name : a .Functor (), arity : Integer (a .Arity ())}})
262
+ }
184
263
for i := 0 ; i < a .Arity (); i ++ {
185
264
c .compileBodyArg (a .Arg (i ), env )
186
265
}
187
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPop })
266
+ c .emit ( instruction {opcode : OpPop })
188
267
default :
189
- c .bytecode = append ( c . bytecode , instruction {opcode : OpPutConst , operand : a })
268
+ c .emit ( instruction {opcode : OpPutConst , operand : a })
190
269
}
191
270
}
192
271
0 commit comments