1/*
2 * gomacro - A Go interpreter with Lisp-like macros
3 *
4 * Copyright (C) 2017-2019 Massimiliano Ghilardi
5 *
6 *     This Source Code Form is subject to the terms of the Mozilla Public
7 *     License, v. 2.0. If a copy of the MPL was not distributed with this
8 *     file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 *
11 * call_multivalue.go
12 *
13 *  Created on May 29, 2017
14 *      Author Massimiliano Ghilardi
15 */
16
17package fast
18
19import (
20	r "reflect"
21)
22
23// call_multivalue compiles foo(bar()) where bar() returns multiple values
24func call_multivalue(call *Call, maxdepth int) I {
25	// no need to special case variadic functions here
26	expr := call.Fun
27	exprfun := expr.AsX1()
28	argfun := call.Args[0].AsXV(COptDefaults)
29	nout := len(call.OutTypes)
30	var ret I
31	switch nout {
32	case 0:
33		if call.Ellipsis {
34			ret = func(env *Env) {
35				funv := exprfun(env)
36				_, argv := argfun(env)
37				callslicexr(funv, argv)
38			}
39		} else {
40			ret = func(env *Env) {
41				funv := exprfun(env)
42				_, argv := argfun(env)
43				callxr(funv, argv)
44			}
45		}
46	case 1:
47		if call.Ellipsis {
48			ret = call_multivalue_ellipsis_ret1(call, maxdepth)
49		} else {
50			ret = call_multivalue_ret1(call, maxdepth)
51		}
52	default:
53		if call.Ellipsis {
54			ret = func(env *Env) (r.Value, []r.Value) {
55				funv := exprfun(env)
56				_, argv := argfun(env)
57				rets := callslicexr(funv, argv)
58				return rets[0], rets
59			}
60		} else {
61			ret = func(env *Env) (r.Value, []r.Value) {
62				funv := exprfun(env)
63				_, argv := argfun(env)
64				rets := callxr(funv, argv)
65				return rets[0], rets
66			}
67		}
68	}
69	return ret
70}
71
72// mandatory optimization: fast_interpreter ASSUMES that expressions
73// returning bool, int, uint, float, complex, string do NOT wrap them in reflect.Value
74func call_multivalue_ret1(call *Call, maxdepth int) I {
75	exprfun := call.Fun.AsX1()
76	argfun := call.Args[0].AsXV(COptDefaults)
77	kout := call.OutTypes[0].Kind()
78	var ret I
79	switch kout {
80	case r.Bool:
81		ret = func(env *Env) bool {
82			funv := exprfun(env)
83			_, argv := argfun(env)
84			retv := callxr(funv, argv)[0]
85			return retv.Bool()
86		}
87	case r.Int:
88		ret = func(env *Env) int {
89			funv := exprfun(env)
90			_, argv := argfun(env)
91			retv := callxr(funv, argv)[0]
92			return int(retv.Int())
93		}
94	case r.Int8:
95		ret = func(env *Env) int8 {
96			funv := exprfun(env)
97			_, argv := argfun(env)
98			retv := callxr(funv, argv)[0]
99			return int8(retv.Int())
100		}
101	case r.Int16:
102		ret = func(env *Env) int16 {
103			funv := exprfun(env)
104			_, argv := argfun(env)
105			retv := callxr(funv, argv)[0]
106			return int16(retv.Int())
107		}
108	case r.Int32:
109		ret = func(env *Env) int32 {
110			funv := exprfun(env)
111			_, argv := argfun(env)
112			retv := callxr(funv, argv)[0]
113			return int32(retv.Int())
114		}
115	case r.Int64:
116		ret = func(env *Env) int64 {
117			funv := exprfun(env)
118			_, argv := argfun(env)
119			retv := callxr(funv, argv)[0]
120			return retv.Int()
121		}
122	case r.Uint:
123		ret = func(env *Env) uint {
124			funv := exprfun(env)
125			_, argv := argfun(env)
126			retv := callxr(funv, argv)[0]
127			return uint(retv.Uint())
128		}
129	case r.Uint8:
130		ret = func(env *Env) uint8 {
131			funv := exprfun(env)
132			_, argv := argfun(env)
133			retv := callxr(funv, argv)[0]
134			return uint8(retv.Uint())
135		}
136	case r.Uint16:
137		ret = func(env *Env) uint16 {
138			funv := exprfun(env)
139			_, argv := argfun(env)
140			retv := callxr(funv, argv)[0]
141			return uint16(retv.Uint())
142		}
143	case r.Uint32:
144		ret = func(env *Env) uint32 {
145			funv := exprfun(env)
146			_, argv := argfun(env)
147			retv := callxr(funv, argv)[0]
148			return uint32(retv.Uint())
149		}
150	case r.Uint64:
151		ret = func(env *Env) uint64 {
152			funv := exprfun(env)
153			_, argv := argfun(env)
154			retv := callxr(funv, argv)[0]
155			return retv.Uint()
156		}
157	case r.Uintptr:
158		ret = func(env *Env) uintptr {
159			funv := exprfun(env)
160			_, argv := argfun(env)
161			retv := callxr(funv, argv)[0]
162			return uintptr(retv.Uint())
163		}
164	case r.Float32:
165		ret = func(env *Env) float32 {
166			funv := exprfun(env)
167			_, argv := argfun(env)
168			retv := callxr(funv, argv)[0]
169			return float32(retv.Float())
170		}
171	case r.Float64:
172		ret = func(env *Env) float64 {
173			funv := exprfun(env)
174			_, argv := argfun(env)
175			retv := callxr(funv, argv)[0]
176			return retv.Float()
177		}
178	case r.Complex64:
179		ret = func(env *Env) complex64 {
180			funv := exprfun(env)
181			_, argv := argfun(env)
182			retv := callxr(funv, argv)[0]
183			return complex64(retv.Complex())
184		}
185	case r.Complex128:
186		ret = func(env *Env) complex128 {
187			funv := exprfun(env)
188			_, argv := argfun(env)
189			retv := callxr(funv, argv)[0]
190			return retv.Complex()
191		}
192	case r.String:
193		ret = func(env *Env) string {
194			funv := exprfun(env)
195			_, argv := argfun(env)
196			retv := callxr(funv, argv)[0]
197			return retv.String()
198		}
199	default:
200		ret = func(env *Env) r.Value {
201			funv := exprfun(env)
202			_, argv := argfun(env)
203			return callxr(funv, argv)[0]
204		}
205	}
206	return ret
207}
208
209// mandatory optimization: fast_interpreter ASSUMES that expressions
210// returning bool, int, uint, float, complex, string do NOT wrap them in reflect.Value
211func call_multivalue_ellipsis_ret1(call *Call, maxdepth int) I {
212	exprfun := call.Fun.AsX1()
213	argfun := call.Args[0].AsXV(COptDefaults)
214	kout := call.OutTypes[0].Kind()
215	var ret I
216	switch kout {
217	case r.Bool:
218		ret = func(env *Env) bool {
219			funv := exprfun(env)
220			_, argv := argfun(env)
221			retv := callslicexr(funv, argv)[0]
222			return retv.Bool()
223		}
224	case r.Int:
225		ret = func(env *Env) int {
226			funv := exprfun(env)
227			_, argv := argfun(env)
228			retv := callslicexr(funv, argv)[0]
229			return int(retv.Int())
230		}
231	case r.Int8:
232		ret = func(env *Env) int8 {
233			funv := exprfun(env)
234			_, argv := argfun(env)
235			retv := callslicexr(funv, argv)[0]
236			return int8(retv.Int())
237		}
238	case r.Int16:
239		ret = func(env *Env) int16 {
240			funv := exprfun(env)
241			_, argv := argfun(env)
242			retv := callslicexr(funv, argv)[0]
243			return int16(retv.Int())
244		}
245	case r.Int32:
246		ret = func(env *Env) int32 {
247			funv := exprfun(env)
248			_, argv := argfun(env)
249			retv := callslicexr(funv, argv)[0]
250			return int32(retv.Int())
251		}
252	case r.Int64:
253		ret = func(env *Env) int64 {
254			funv := exprfun(env)
255			_, argv := argfun(env)
256			retv := callslicexr(funv, argv)[0]
257			return retv.Int()
258		}
259	case r.Uint:
260		ret = func(env *Env) uint {
261			funv := exprfun(env)
262			_, argv := argfun(env)
263			retv := callslicexr(funv, argv)[0]
264			return uint(retv.Uint())
265		}
266	case r.Uint8:
267		ret = func(env *Env) uint8 {
268			funv := exprfun(env)
269			_, argv := argfun(env)
270			retv := callslicexr(funv, argv)[0]
271			return uint8(retv.Uint())
272		}
273	case r.Uint16:
274		ret = func(env *Env) uint16 {
275			funv := exprfun(env)
276			_, argv := argfun(env)
277			retv := callslicexr(funv, argv)[0]
278			return uint16(retv.Uint())
279		}
280	case r.Uint32:
281		ret = func(env *Env) uint32 {
282			funv := exprfun(env)
283			_, argv := argfun(env)
284			retv := callslicexr(funv, argv)[0]
285			return uint32(retv.Uint())
286		}
287	case r.Uint64:
288		ret = func(env *Env) uint64 {
289			funv := exprfun(env)
290			_, argv := argfun(env)
291			retv := callslicexr(funv, argv)[0]
292			return retv.Uint()
293		}
294	case r.Uintptr:
295		ret = func(env *Env) uintptr {
296			funv := exprfun(env)
297			_, argv := argfun(env)
298			retv := callslicexr(funv, argv)[0]
299			return uintptr(retv.Uint())
300		}
301	case r.Float32:
302		ret = func(env *Env) float32 {
303			funv := exprfun(env)
304			_, argv := argfun(env)
305			retv := callslicexr(funv, argv)[0]
306			return float32(retv.Float())
307		}
308	case r.Float64:
309		ret = func(env *Env) float64 {
310			funv := exprfun(env)
311			_, argv := argfun(env)
312			retv := callslicexr(funv, argv)[0]
313			return retv.Float()
314		}
315	case r.Complex64:
316		ret = func(env *Env) complex64 {
317			funv := exprfun(env)
318			_, argv := argfun(env)
319			retv := callslicexr(funv, argv)[0]
320			return complex64(retv.Complex())
321		}
322	case r.Complex128:
323		ret = func(env *Env) complex128 {
324			funv := exprfun(env)
325			_, argv := argfun(env)
326			retv := callslicexr(funv, argv)[0]
327			return retv.Complex()
328		}
329	case r.String:
330		ret = func(env *Env) string {
331			funv := exprfun(env)
332			_, argv := argfun(env)
333			retv := callslicexr(funv, argv)[0]
334			return retv.String()
335		}
336	default:
337		ret = func(env *Env) r.Value {
338			funv := exprfun(env)
339			_, argv := argfun(env)
340			return callslicexr(funv, argv)[0]
341		}
342	}
343	return ret
344}
345