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 * expr1.go 12 * 13 * Created on Apr 03, 2017 14 * Author Massimiliano Ghilardi 15 */ 16 17package fast 18 19import ( 20 "go/constant" 21 r "reflect" 22 23 "github.com/cosmos72/gomacro/base/output" 24 "github.com/cosmos72/gomacro/base/reflect" 25 "github.com/cosmos72/gomacro/base/untyped" 26 xr "github.com/cosmos72/gomacro/xreflect" 27) 28 29func (c *Comp) litValue(value I) Lit { 30 return Lit{Type: c.TypeOf(value), Value: value} 31} 32 33func (c *Comp) exprUntypedLit(kind untyped.Kind, obj constant.Value) *Expr { 34 return &Expr{Lit: Lit{Type: c.TypeOfUntypedLit(), Value: untyped.MakeLit(kind, obj, &c.Universe.BasicTypes)}} 35} 36 37func (c *Comp) exprValue(t xr.Type, value I) *Expr { 38 if t == nil { 39 t = c.TypeOf(value) 40 } 41 return exprValue(t, value) 42} 43 44func exprValue(t xr.Type, value I) *Expr { 45 if t == nil { 46 output.Errorf("internal error! exprValue() value = %v invoked with type = nil", value) 47 } 48 return &Expr{ 49 Lit: Lit{Type: t, Value: value}, 50 EFlags: EFlag4Value(value), 51 } 52} 53 54func exprLit(lit Lit, sym *Symbol) *Expr { 55 return &Expr{Lit: lit, Sym: sym, EFlags: EFlag4Value(lit.Value)} 56} 57 58func exprFun(t xr.Type, fun I) *Expr { 59 return &Expr{Lit: Lit{Type: t}, Fun: fun} 60} 61 62func exprX1(t xr.Type, fun func(env *Env) r.Value) *Expr { 63 return &Expr{Lit: Lit{Type: t}, Fun: fun} 64} 65 66func exprXV(types []xr.Type, fun func(env *Env) (r.Value, []r.Value)) *Expr { 67 if len(types) == 1 { 68 return &Expr{Lit: Lit{Type: types[0]}, Fun: fun} 69 } else { 70 return &Expr{Lit: Lit{Type: types[0]}, Types: types, Fun: fun} 71 } 72} 73 74func expr0(fun func(env *Env)) *Expr { 75 return &Expr{Types: zeroTypes, Fun: fun} 76} 77 78func (c *Comp) exprBool(fun func(env *Env) bool) *Expr { 79 return &Expr{Lit: Lit{Type: c.TypeOfBool()}, Fun: fun} 80} 81 82func (c *Comp) exprUint8(fun func(env *Env) uint8) *Expr { 83 return &Expr{Lit: Lit{Type: c.TypeOfUint8()}, Fun: fun} 84} 85 86func (c *Comp) exprString(fun func(env *Env) string) *Expr { 87 return &Expr{Lit: Lit{Type: c.TypeOfString()}, Fun: fun} 88} 89 90func (expr *Expr) EvalConst(opts CompileOptions) I { 91 if expr == nil { 92 return nil 93 } 94 if expr.Const() { 95 if opts == COptDefaults && expr.Untyped() { 96 return expr.ConstTo(expr.DefaultType()) 97 } 98 return expr.Value 99 } 100 ret := expr.AsX1()(nil) 101 if ret == reflect.None { 102 output.Errorf("constant should evaluate to a single value, found no values at all") 103 return nil 104 } 105 var value I 106 if ret != reflect.Nil { 107 value = ret.Interface() 108 } 109 expr.Value = value 110 expr.EFlags = EFlag4Value(value) 111 expr.Fun = nil // no longer needed, will be recreated if needed as a wrapper for the computed value 112 return value 113} 114