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 * literal.go
12 *
13 *  Created on Apr 01, 2017
14 *      Author Massimiliano Ghilardi
15 */
16
17package fast
18
19import (
20	"go/ast"
21	"go/constant"
22	"go/token"
23	"math/big"
24	r "reflect"
25
26	"github.com/cosmos72/gomacro/base/output"
27
28	"github.com/cosmos72/gomacro/base/reflect"
29	"github.com/cosmos72/gomacro/base/untyped"
30	xr "github.com/cosmos72/gomacro/xreflect"
31)
32
33func (c *Comp) BasicLit(node *ast.BasicLit) *Expr {
34	str := node.Value
35	var kind untyped.Kind
36	var label string
37	switch node.Kind {
38	case token.INT:
39		kind, label = untyped.Int, "integer"
40	case token.FLOAT:
41		kind, label = untyped.Float, "float"
42	case token.IMAG:
43		kind, label = untyped.Complex, "complex"
44	case token.CHAR:
45		kind, label = untyped.Rune, "rune"
46	case token.STRING:
47		kind, label = untyped.String, "string"
48	default:
49		c.Errorf("unsupported basic literal: %v", node)
50		return nil
51	}
52	obj := constant.MakeFromLiteral(str, node.Kind, 0)
53	if obj.Kind() == constant.Unknown {
54		c.Errorf("invalid %s literal: %v", label, str)
55		return nil
56	}
57	return c.exprUntypedLit(kind, obj)
58}
59
60func isLiteral(x interface{}) bool {
61	if x == nil {
62		return true
63	}
64	rtype := r.TypeOf(x)
65	switch reflect.Category(rtype.Kind()) {
66	case r.Bool, r.Int, r.Uint, r.Float64, r.Complex128, r.String:
67		return true
68	}
69	_, ok := x.(UntypedLit)
70	return ok
71}
72
73func isLiteralNumber(x I, n int64) bool {
74	if x == nil {
75		return false
76	}
77	v := r.ValueOf(x)
78	switch reflect.Category(v.Kind()) {
79	case r.Bool:
80		return false
81	case r.Int:
82		return v.Int() == n
83	case r.Uint:
84		// n == -1 means "unsigned integer equals its maximum value"
85		// similarly, n == -2 means "unsigned integer equals its maximum value minus 1"
86		// and so on...
87		return v.Uint() == uint64(n)
88	case r.Float64:
89		return v.Float() == float64(n)
90	case r.Complex128:
91		return v.Complex() == complex(float64(n), 0)
92	case r.String:
93		return false
94	}
95	// no luck yet... try harder
96	switch x := x.(type) {
97	case r.Value:
98		return false
99	case UntypedLit:
100		return x.EqualInt64(n)
101	}
102	output.Errorf("isLiteralNumber: unexpected literal type %v <%v>", x, r.TypeOf(x))
103	return false
104}
105
106// ================================= ConstTo =================================
107
108// ConstTo checks that a constant Expr can be used as the given type.
109// panics if not constant, or if Expr is a typed constant of different type
110// actually performs type conversion (and subsequent overflow checks) ONLY on untyped constants.
111func (e *Expr) ConstTo(t xr.Type) I {
112	if !e.Const() {
113		output.Errorf("internal error: expression is not constant, use Expr.To() instead of Expr.ConstTo() to convert from <%v> to <%v>", e.Type, t)
114	}
115	val := e.Lit.ConstTo(t)
116	fun := makeMathBigFun(val)
117	if fun != nil {
118		// no longer a constant
119		e.Lit.Value = nil
120		e.Fun = fun
121	} else {
122		if e.Fun != nil {
123			// e.Fun is no longer valid, recompute it
124			e.WithFun()
125		}
126	}
127	return val
128}
129
130// ConstTo checks that a Lit can be used as the given type.
131// panics if Lit is a typed constant of different type
132// actually performs type conversion (and subsequent overflow checks) ONLY on untyped constants.
133func (lit *Lit) ConstTo(t xr.Type) I {
134	value := lit.Value
135	// output.Debugf("Lit.ConstTo(): converting constant %v <%v> (stored as <%v>) to <%v>", value, TypeOf(value), lit.Type, t)
136	if t == nil {
137		// only literal nil has type nil
138		if value != nil {
139			output.Errorf("cannot convert constant %v <%v> to <nil>", value, lit.Type)
140		}
141		return nil
142	}
143	// stricter than t == lit.Type
144	tfrom := lit.Type
145	if tfrom != nil && t != nil && tfrom.IdenticalTo(t) {
146		return value
147	}
148	switch x := value.(type) {
149	case UntypedLit:
150		val := x.Convert(t)
151		lit.Type = t
152		lit.Value = val
153		// output.Debugf("UntypedLit.Convert(): converted untyped constant %v to %v <%v> (stored as <%v>)", x, val, TypeOf(val), t)
154		return val
155	case nil:
156		// literal nil can only be converted to nillable types
157		if reflect.IsNillableKind(t.Kind()) {
158			lit.Type = t
159			return nil
160			// lit.Value = r.Zero(t).Interface()
161			// return lit.Value
162		}
163	}
164	if tfrom != nil && t != nil && (tfrom.AssignableTo(t) || t.Kind() == r.Interface && tfrom.Implements(t)) {
165		lit.Type = t
166		// FIXME: use (*Comp).Converter(), requires a *Comp parameter
167		lit.Value = convert(r.ValueOf(value), t.ReflectType()).Interface()
168		return lit.Value
169	}
170	output.Errorf("cannot convert typed constant %v <%v> to <%v>%s", value, lit.Type, t, interfaceMissingMethod(lit.Type, t))
171	return nil
172}
173
174// return a closure that duplicates at each invokation any *big.Int, *big.Rat, *big.Float passed as 'val'
175func makeMathBigFun(val I) func(*Env) r.Value {
176	switch a := val.(type) {
177	case *big.Int:
178		return func(*Env) r.Value {
179			var b big.Int
180			b.Set(a)
181			return r.ValueOf(&b)
182		}
183	case *big.Rat:
184		return func(*Env) r.Value {
185			var b big.Rat
186			b.Set(a)
187			return r.ValueOf(&b)
188		}
189	case *big.Float:
190		return func(*Env) r.Value {
191			var b big.Float
192			b.Set(a)
193			return r.ValueOf(&b)
194		}
195	default:
196		return nil
197	}
198}
199
200// ================================= DefaultType =================================
201
202// DefaultType returns the default type of an expression.
203func (e *Expr) DefaultType() xr.Type {
204	if e.Untyped() {
205		return e.Lit.DefaultType()
206	}
207	return e.Type
208}
209
210// DefaultType returns the default type of a constant.
211func (lit *Lit) DefaultType() xr.Type {
212	switch x := lit.Value.(type) {
213	case UntypedLit:
214		return x.DefaultType()
215	default:
216		return lit.Type
217	}
218}
219
220// SetTypes sets the expression result types
221func (e *Expr) SetTypes(tout []xr.Type) {
222	switch len(tout) {
223	case 0:
224		e.Type = nil
225		e.Types = tout
226	case 1:
227		e.Type = tout[0]
228		e.Types = nil
229	default:
230		e.Type = tout[0]
231		e.Types = tout
232	}
233}
234
235/* used?
236
237// Set sets the expression value to the given (typed or untyped) constant
238func (e *Expr) Set(x I) {
239	e.Lit.Set(x)
240	e.Types = nil
241	e.Fun = nil
242	e.IsNil = x == nil
243}
244
245// Set sets the Lit to the given typed constant
246func (lit *Lit) Set(x I) {
247	t := TypeOf(x)
248	if !isLiteral(x) {
249		Errorf("cannot set Lit to non-literal value %v <%v>", x, t)
250	}
251	lit.Type = t
252	lit.Value = x
253}
254*/
255
256// To checks that an Expr can be used as (i.e. is assignable to) the given type,
257// and converts Expr to the given type.
258// panics if Expr has an incompatible type.
259func (e *Expr) To(c *Comp, t xr.Type) {
260	if e.Const() {
261		e.ConstTo(t)
262		return
263	}
264	if e.Type.IdenticalTo(t) {
265		return
266	}
267	if !e.Type.AssignableTo(t) {
268		c.Errorf("cannot use <%v> as <%v>", e.Type, t)
269	}
270	k := e.Type.Kind()
271	if reflect.IsOptimizedKind(k) {
272		if k == t.Kind() {
273			// same optimized representation
274			e.Type = t
275			return
276		} else if t.Kind() == r.Interface {
277			e.Fun = e.AsX1()
278			e.Type = t
279			return
280		}
281		c.Errorf("internal error: cannot use <%v> as <%v> (should not happen, <%v> is assignable to <%v>", e.Type, t, e.Type, t)
282	}
283	fun := e.AsX1()
284	rtype := t.ReflectType()
285	zero := r.Zero(rtype)
286
287	if conv := c.Converter(e.Type, t); conv == nil {
288		e.Fun = func(env *Env) r.Value {
289			v := fun(env)
290			if !v.IsValid() {
291				v = zero
292			}
293			return v
294		}
295	} else {
296		e.Fun = func(env *Env) r.Value {
297			v := fun(env)
298			if !v.IsValid() {
299				v = zero
300			} else {
301				v = conv(v)
302			}
303			return v
304		}
305	}
306	e.Type = t
307}
308
309// WithFun ensures that Expr.Fun is a closure that will return the expression result:
310//
311// if Expr is an untyped constant, WithFun converts the constant to its default type (panics on overflows),
312//    then sets Expr.Fun to a closure that will return such constant.
313// if Expr is a typed constant, WithFun sets Expr.Fun to a closure that will return such constant.
314// if Expr is not a constant, WithFun does nothing (Expr.Fun must be set already)
315func (e *Expr) WithFun() I {
316	if !e.Const() {
317		return e.Fun
318	}
319	var fun I
320again:
321	value := e.Value
322	v := r.ValueOf(value)
323	t := e.Type
324	if t == nil {
325		e.Fun = eNil
326		return eNil
327	}
328	if value == nil {
329		if !reflect.IsNillableKind(t.Kind()) {
330			output.Errorf("internal error: constant of type <%v> cannot be nil", t)
331		}
332		zero := r.Zero(t.ReflectType())
333		fun = func(*Env) r.Value {
334			return zero
335		}
336		e.Fun = fun
337		return fun
338	}
339	rtactual := r.TypeOf(value)
340	rtexpected := t.ReflectType()
341	if rtexpected != rtactual {
342		if rtexpected.Kind() == r.Interface && rtactual.Implements(rtexpected) {
343			v = convert(v, rtexpected)
344		} else {
345			output.Errorf("internal error: constant %v <%v> was assumed to have type <%v>", value, rtactual, rtexpected)
346		}
347	}
348	switch v.Kind() {
349	case r.Invalid:
350		fun = eNil
351	case r.Bool:
352		if v.Bool() {
353			fun = eTrue
354		} else {
355			fun = eFalse
356		}
357	case r.Int:
358		x := int(v.Int())
359		fun = func(env *Env) int {
360			return x
361		}
362	case r.Int8:
363		x := int8(v.Int())
364		fun = func(env *Env) int8 {
365			return x
366		}
367	case r.Int16:
368		x := int16(v.Int())
369		fun = func(env *Env) int16 {
370			return x
371		}
372	case r.Int32:
373		x := int32(v.Int())
374		fun = func(env *Env) int32 {
375			return x
376		}
377	case r.Int64:
378		x := v.Int()
379		fun = func(env *Env) int64 {
380			return x
381		}
382	case r.Uint:
383		x := uint(v.Uint())
384		fun = func(env *Env) uint {
385			return x
386		}
387	case r.Uint8:
388		x := uint8(v.Uint())
389		fun = func(env *Env) uint8 {
390			return x
391		}
392	case r.Uint16:
393		x := uint16(v.Uint())
394		fun = func(env *Env) uint16 {
395			return x
396		}
397	case r.Uint32:
398		x := uint32(v.Uint())
399		fun = func(env *Env) uint32 {
400			return x
401		}
402	case r.Uint64:
403		x := v.Uint()
404		fun = func(env *Env) uint64 {
405			return x
406		}
407	case r.Uintptr:
408		x := uintptr(v.Uint())
409		fun = func(env *Env) uintptr {
410			return x
411		}
412	case r.Float32:
413		x := float32(v.Float())
414		fun = func(env *Env) float32 {
415			return x
416		}
417	case r.Float64:
418		x := v.Float()
419		fun = func(env *Env) float64 {
420			return x
421		}
422	case r.Complex64:
423		x := complex64(v.Complex())
424		fun = func(env *Env) complex64 {
425			return x
426		}
427	case r.Complex128:
428		x := v.Complex()
429		fun = func(env *Env) complex128 {
430			return x
431		}
432	case r.String:
433		x := v.String()
434		fun = func(env *Env) string {
435			return x
436		}
437	default:
438		if t.ReflectType() == rtypeOfUntypedLit {
439			e.ConstTo(e.DefaultType())
440			goto again
441		}
442		fun = func(env *Env) r.Value {
443			return v
444		}
445	}
446	e.Fun = fun
447	return fun
448}
449