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 * global.go
12 *
13 *  Created on Apr 01, 2017
14 *      Author Massimiliano Ghilardi
15 */
16
17package fast
18
19import (
20	"fmt"
21	"go/ast"
22	"go/constant"
23	"go/token"
24	r "reflect"
25	"sort"
26
27	"github.com/cosmos72/gomacro/atomic"
28	. "github.com/cosmos72/gomacro/base"
29	"github.com/cosmos72/gomacro/base/output"
30	"github.com/cosmos72/gomacro/base/untyped"
31	"github.com/cosmos72/gomacro/jit"
32	xr "github.com/cosmos72/gomacro/xreflect"
33)
34
35type I = interface{}
36
37// ================================= Untyped =================================
38
39type UntypedLit = untyped.Lit
40
41var untypedOne = UntypedLit{Kind: untyped.Int, Val: constant.MakeInt64(1)}
42
43// ================================= Lit =================================
44
45// Lit represents a literal value, i.e. a typed or untyped constant
46type Lit struct {
47
48	// Type is nil for literal nils.
49	// For all other literals, Type is xr.TypeOf(Lit.Value)
50	//
51	// when Lit is embedded in other structs that represent non-constant expressions,
52	// Type is the first type returned by the expression (nil if returns no values)
53	Type xr.Type
54
55	// Value is one of:
56	//   nil, bool, int, int8, int16, int32, int64,
57	//   uint, uint8, uint16, uint32, uint64, uintptr,
58	//   float32, float64, complex64, complex128, string,
59	//   UntypedLit
60	//
61	// when Lit is embedded in other structs that represent non-constant expressions,
62	// Value is usually nil
63	//
64	// when Lit is embedded in a Bind with class == TemplateFuncBind,
65	// Value is the *TemplateFunc containing the function source code
66	// to be specialized and compiled upon instantiation.
67	Value I
68}
69
70// Untyped returns true if Lit is an untyped constant
71func (lit *Lit) Untyped() bool {
72	_, ok := lit.Value.(UntypedLit)
73	return ok
74}
75
76// UntypedKind returns the reflect.Kind of untyped constants,
77// i.e. their "default type"
78func (lit *Lit) UntypedKind() untyped.Kind {
79	if untyp, ok := lit.Value.(UntypedLit); ok {
80		return untyp.Kind
81	} else {
82		return untyped.None
83	}
84}
85
86func (lit *Lit) ConstValue() r.Value {
87	v := r.ValueOf(lit.Value)
88	if lit.Type != nil {
89		rtype := lit.Type.ReflectType()
90		if !v.IsValid() {
91			v = r.Zero(rtype)
92		} else if !lit.Untyped() && v.Type() != rtype {
93			v = convert(v, rtype)
94		}
95	}
96	return v
97}
98
99func (lit Lit) String() string {
100	switch val := lit.Value.(type) {
101	case string, nil:
102		return fmt.Sprintf("%#v", val)
103	default:
104		return fmt.Sprintf("%v", val)
105	}
106}
107
108// ================================= EFlags =================================
109
110// EFlags represents the flags of an expression
111type EFlags uint32
112
113const (
114	EIsNil EFlags = 1 << iota
115	EIsTypeAssert
116)
117
118func (f EFlags) IsNil() bool {
119	return f&EIsNil != 0
120}
121
122func MakeEFlag(flag bool, iftrue EFlags) EFlags {
123	if flag {
124		return iftrue
125	}
126	return 0
127}
128
129func EFlag4Value(value I) EFlags {
130	if value == nil {
131		return EIsNil
132	}
133	return 0
134}
135
136// ================================= Expr =================================
137
138// Expr represents an expression in the "compiler"
139type Expr struct {
140	Lit
141	Types []xr.Type // in case the expression produces multiple values. if nil, use Lit.Type.
142	Fun   I         // function that evaluates the expression at runtime.
143	Sym   *Symbol   // in case the expression is a symbol
144	Jit   jit.Expr  // expression to jit-compile, or nil if not supported
145	EFlags
146}
147
148func (e *Expr) Const() bool {
149	return e.Value != nil || e.IsNil()
150}
151
152// NumOut returns the number of values that an expression will produce when evaluated
153func (e *Expr) NumOut() int {
154	if e.Types == nil {
155		return 1
156	}
157	return len(e.Types)
158}
159
160// Out returns the i-th type that an expression will produce when evaluated
161func (e *Expr) Out(i int) xr.Type {
162	if i == 0 && e.Types == nil {
163		return e.Type
164	}
165	return e.Types[i]
166}
167
168func (e *Expr) String() string {
169	if e == nil {
170		return "nil"
171	}
172	var str string
173	if e.Const() {
174		str = fmt.Sprintf("Expr{Type: %v, Value: %v}", e.Type, e.Lit.String())
175	} else if e.NumOut() == 1 {
176		str = fmt.Sprintf("Expr{Type: %v, Fun: %#v}", e.Type, e.Fun)
177	} else {
178		str = fmt.Sprintf("Expr{Types: %v, Fun: %#v}", e.Types, e.Fun)
179	}
180	return str
181}
182
183// ================================= Stmt =================================
184
185// Stmt represents a statement in the fast interpreter
186type Stmt func(*Env) (Stmt, *Env)
187
188// ================================= Builtin =================================
189
190// Builtin represents a builtin function in the fast interpreter
191type Builtin struct {
192	// interpreted code should not access "compile": not exported.
193	// compile usually needs to modify Symbol: pass it by value.
194	Compile func(c *Comp, sym Symbol, node *ast.CallExpr) *Call
195	ArgMin  uint16
196	ArgMax  uint16
197}
198
199// ================================= Function =================================
200
201// Function represents a function that accesses *Interp in the fast interpreter
202type Function struct {
203	Fun  interface{}
204	Type xr.Type
205}
206
207// ================================= Macro =================================
208
209// Macro represents a macro in the fast interpreter
210type Macro struct {
211	closure func(args []r.Value) (results []r.Value)
212	argNum  int
213}
214
215// ================================= BindClass =================================
216
217// BindDescriptor uses two bits to store the class.
218// use all remaining bits as unsigned => we lose only one bit
219// when representing non-negative ints
220type BindClass uint
221
222const (
223	ConstBind BindClass = iota
224	FuncBind
225	VarBind
226	IntBind
227	TemplateFuncBind
228	TemplateTypeBind
229)
230
231func (class BindClass) String() string {
232	switch class {
233	case ConstBind:
234		return "const"
235	case FuncBind:
236		return "func"
237	case VarBind:
238		return "var"
239	case IntBind:
240		return "intvar"
241	case TemplateFuncBind:
242		return "template func"
243	case TemplateTypeBind:
244		return "template type"
245	default:
246		return fmt.Sprintf("unknown%d", uint(class))
247	}
248}
249
250// ================================== BindDescriptor =================================
251
252// the zero value of BindDescriptor is a valid descriptor for all constants,
253// and also for functions and variables named "_"
254type BindDescriptor BindClass
255
256const (
257	bindClassMask  = BindClass(0x7)
258	bindIndexShift = 3
259
260	NoIndex             = int(-1)                   // index of functions, variables named "_" and of constants
261	ConstBindDescriptor = BindDescriptor(ConstBind) // bind descriptor for all constants
262)
263
264func (class BindClass) MakeDescriptor(index int) BindDescriptor {
265	class &= bindClassMask
266	return BindDescriptor((index+1)<<bindIndexShift | int(class))
267}
268
269// IntBind returns true if BindIndex refers to a slot in Env.IntBinds (the default is a slot in Env.Binds)
270func (desc BindDescriptor) Class() BindClass {
271	return BindClass(desc) & bindClassMask
272}
273
274// Index returns the slice index to use in Env.Binds or Env.IntBinds to access a variable or function.
275// returns NoIndex for variables and functions named "_"
276func (desc BindDescriptor) Index() int {
277	index := int(desc>>bindIndexShift) - 1
278	// debugf("BindDescriptor=%v, class=%v, index=%v", desc, desc.Class(), index)
279	return index
280}
281
282func (desc BindDescriptor) Settable() bool {
283	class := desc.Class()
284	return class == IntBind || class == VarBind
285}
286
287func (desc BindDescriptor) String() string {
288	return fmt.Sprintf("%s index=%d", desc.Class(), desc.Index())
289}
290
291// ================================== Bind =================================
292
293// Bind represents a constant, variable, function or builtin in the "compiler"
294type Bind struct {
295	Lit
296	Desc BindDescriptor
297	Name string
298}
299
300func (bind *Bind) String() string {
301	return fmt.Sprintf("{%s name=%q value=%v type=<%v>}", bind.Desc, bind.Name, bind.Lit.Value, bind.Lit.Type)
302}
303
304func (bind *Bind) Const() bool {
305	return bind.Desc.Class() == ConstBind
306}
307
308// return bind value for constant binds.
309// if bind is untyped constant, returns UntypedLit wrapped in reflect.Value
310func (bind *Bind) ConstValue() r.Value {
311	if !bind.Const() {
312		return Nil
313	}
314	return bind.Lit.ConstValue()
315}
316
317// return bind value.
318// if bind is untyped constant, returns UntypedLit wrapped in reflect.Value
319func (bind *Bind) RuntimeValue(g *CompGlobals, env *Env) r.Value {
320	var v r.Value
321	switch bind.Desc.Class() {
322	case ConstBind:
323		v = bind.Lit.ConstValue()
324	case IntBind:
325		expr := bind.intExpr(g)
326		// no need for Interp.RunExpr(): expr is a local variable,
327		// not a statement or a function call that may be stopped by the debugger
328		v = expr.AsX1()(env)
329	case VarBind, FuncBind:
330		v = env.Vals[bind.Desc.Index()]
331	case TemplateFuncBind, TemplateTypeBind:
332		if GENERICS_V1 {
333			v = bind.Lit.ConstValue()
334			break
335		}
336		fallthrough
337	default:
338		output.Errorf("Symbol %q: unsupported class: %v", bind.Name, bind.Desc.Class())
339	}
340	return v
341}
342
343func (bind *Bind) AsVar(upn int, opt PlaceOption) *Var {
344	class := bind.Desc.Class()
345	switch class {
346	case VarBind, IntBind:
347		return &Var{Upn: upn, Desc: bind.Desc, Type: bind.Type, Name: bind.Name}
348	default:
349		output.Errorf("%s a %s: %s <%v>", opt, class, bind.Name, bind.Type)
350		return nil
351	}
352}
353
354func (bind *Bind) AsSymbol(upn int) *Symbol {
355	return &Symbol{Bind: *bind, Upn: upn}
356}
357
358func (c *Comp) BindUntyped(kind untyped.Kind, value constant.Value) *Bind {
359	untypedlit := untyped.MakeLit(kind, value, &c.Universe.BasicTypes)
360	return &Bind{Lit: Lit{Type: c.TypeOfUntypedLit(), Value: untypedlit}, Desc: ConstBindDescriptor}
361}
362
363// ================================== Symbol, Var, Place =================================
364
365// Symbol represents a resolved constant, function, variable or builtin
366type Symbol struct {
367	Bind
368	Upn int
369}
370
371func (sym *Symbol) AsVar(opt PlaceOption) *Var {
372	return sym.Bind.AsVar(sym.Upn, opt)
373}
374
375func (sym *Symbol) String() string {
376	return fmt.Sprintf("Symbol{%v %q %v idx=%v upn=%v}", sym.Desc.Class(), sym.Name, sym.Type, sym.Desc.Index(), sym.Upn)
377}
378
379// Var represents a settable variable
380type Var struct {
381	// when Var is embedded in other structs that represent non-identifiers,
382	// Upn and Desc are usually the zero values
383	Upn  int
384	Desc BindDescriptor
385	Type xr.Type
386	Name string
387}
388
389func (va *Var) AsSymbol() *Symbol {
390	return &Symbol{
391		Bind: Bind{
392			Lit:  Lit{Type: va.Type},
393			Desc: va.Desc,
394			Name: va.Name,
395		},
396		Upn: va.Upn,
397	}
398}
399
400func (va *Var) AsPlace() *Place {
401	return &Place{Var: *va}
402}
403
404func (va *Var) String() string {
405	return fmt.Sprintf("Var{%v %q %v idx=%v upn=%v}", va.Desc.Class(), va.Name, va.Type, va.Desc.Index(), va.Upn)
406}
407
408// Place represents a settable place or, equivalently, its address
409type Place struct {
410	Var
411	// Fun is nil for variables.
412	// For non-variables, returns a settable and addressable reflect.Value: the place itself.
413	// For map[key], Fun returns the map itself (which may NOT be settable).
414	// Call Fun only once, it may have side effects!
415	Fun func(*Env) r.Value
416	// Addr is nil for variables.
417	// For non-variables, it will return the address of the place.
418	// For map[key], it is nil since map[key] is not addressable
419	// Call Addr only once, it may have side effects!
420	Addr func(*Env) r.Value
421	// used only for map[key], returns key. call it only once, it may have side effects!
422	MapKey  func(*Env) r.Value
423	MapType xr.Type
424}
425
426func (place *Place) IsVar() bool {
427	return place.Fun == nil
428}
429
430type PlaceOption bool // the reason why we want a place: either to write into it, or to take its address
431
432const (
433	PlaceSettable PlaceOption = false
434	PlaceAddress  PlaceOption = true
435)
436
437func (opt PlaceOption) String() string {
438	if opt == PlaceAddress {
439		return "cannot take the address of"
440	} else {
441		return "cannot assign to"
442	}
443}
444
445// ================================== Comp, Env =================================
446
447type CompileOptions int
448
449const (
450	COptKeepUntyped CompileOptions = 1 << iota // if set, Compile() on expressions will keep all untyped constants as such (in expressions where Go compiler would compute an untyped constant too)
451	COptDefaults    CompileOptions = 0
452)
453
454type Code struct {
455	List       []Stmt
456	DebugPos   []token.Pos // for debugging interpreted code: position of each statement
457	WithDefers bool        // true if code contains some defers
458}
459
460type LoopInfo struct {
461	Break      *int
462	Continue   *int
463	ThisLabels []string // sorted. for labeled "switch" and "for"
464}
465
466func (l *LoopInfo) HasLabel(label string) bool {
467	i := sort.SearchStrings(l.ThisLabels, label)
468	return i >= 0 && i < len(l.ThisLabels) && l.ThisLabels[i] == label
469}
470
471type FuncInfo struct {
472	Name         string
473	Param        []*Bind
474	Result       []*Bind
475	NamedResults bool
476}
477
478const (
479	poolCapacity = 32
480)
481
482type ExecFlags uint32
483
484const (
485	EFStartDefer ExecFlags = 1 << iota // true next executed function body is a defer
486	EFDefer                            // function body being executed is a defer
487	EFDebug                            // function body is executed with debugging enabled
488)
489
490func (ef ExecFlags) StartDefer() bool {
491	return ef&EFStartDefer != 0
492}
493
494func (ef ExecFlags) IsDefer() bool {
495	return ef&EFDefer != 0
496}
497
498func (ef ExecFlags) IsDebug() bool {
499	return ef&EFDebug != 0
500}
501
502func (ef *ExecFlags) SetDefer(flag bool) {
503	if flag {
504		(*ef) |= EFDefer
505	} else {
506		(*ef) &^= EFDefer
507	}
508}
509
510func (ef *ExecFlags) SetStartDefer(flag bool) {
511	if flag {
512		(*ef) |= EFStartDefer
513	} else {
514		(*ef) &^= EFStartDefer
515	}
516}
517
518func (ef *ExecFlags) SetDebug(flag bool) {
519	if flag {
520		(*ef) |= EFDebug
521	} else {
522		(*ef) &^= EFDebug
523	}
524}
525
526type DebugOp struct {
527	// statements at env.CallDepth < Depth will be executed in single-stepping mode,
528	// i.e. invoking the debugger after every statement
529	Depth int
530	// nil = do not panic.
531	// otherwise, address of value to panic() in order to terminate execution
532	Panic *interface{}
533}
534
535var (
536	// NEVER modify these!
537	DebugOpContinue = DebugOp{0, nil}
538	DebugOpStep     = DebugOp{MaxInt, nil}
539)
540
541type Debugger interface {
542	Breakpoint(ir *Interp, env *Env) DebugOp
543	At(ir *Interp, env *Env) DebugOp
544}
545
546// IrGlobals contains interpreter configuration
547type IrGlobals struct {
548	gls  map[uintptr]*Run
549	lock atomic.SpinLock
550	Globals
551}
552
553// Run contains per-goroutine interpreter runtime bookeeping information
554type Run struct {
555	*IrGlobals
556	goid         uintptr // owner goroutine id
557	Interrupt    Stmt
558	Signals      Signals // set by defer, return, breakpoint, debugger and Run.interrupt(os.Signal)
559	ExecFlags    ExecFlags
560	CurrEnv      *Env        // caller of current function. used ONLY at function entry to build call stack
561	InstallDefer func()      // defer function to be installed
562	DeferOfFun   *Env        // function whose defer are running
563	PanicFun     *Env        // the currently panicking function
564	Panic        interface{} // current panic. needed for recover()
565	CmdOpt       CmdOpt
566	Debugger     Debugger
567	DebugDepth   int // depth of function to debug with single-step
568	PoolSize     int
569	Pool         [poolCapacity]*Env
570}
571
572// CompGlobals contains interpreter compile bookeeping information
573type CompGlobals struct {
574	*IrGlobals
575	Universe     *xr.Universe
576	KnownImports map[string]*Import // map[path]*Import cache of known imports
577	interf2proxy map[r.Type]r.Type  // interface -> proxy
578	proxy2interf map[r.Type]xr.Type // proxy -> interface
579	Prompt       string
580	Jit          *Jit
581}
582
583func (cg *CompGlobals) CompileOptions() CompileOptions {
584	var opts CompileOptions
585	if cg.Options&OptKeepUntyped != 0 {
586		opts = COptKeepUntyped
587	}
588	return opts
589}
590
591type CompBinds struct {
592	Binds      map[string]*Bind
593	BindNum    int // len(Binds) == BindNum + IntBindNum + # of constants
594	IntBindNum int
595	// if address of some Env.Ints[index] was taken, we must honor it:
596	// we can no longer reallocate Env.Ints[], thus we cannot declare IntBind variables
597	// beyond Env.Ints[] capacity. In such case, we set IntBindMax to cap(Env.Ints):
598	// Comp.NewBind() will allocate IntBind variables only up to IntBindMax,
599	// then switch and allocate them as VarBind instead (they are slower and each one allocates memory)
600	IntBindMax int
601	Types      map[string]xr.Type
602	Name       string // set by "package" directive
603	Path       string
604}
605
606// Comp is a tree-of-closures builder: it transforms ast.Nodes into closures
607// for faster execution. Consider it a poor man's compiler (hence the name)
608type Comp struct {
609	*CompGlobals
610	CompBinds
611	// UpCost is the number of *Env.Outer hops to perform at runtime to reach the *Env corresponding to *Comp.Outer
612	// usually equals one. will be zero if this *Comp defines no local variables/functions.
613	UpCost    int
614	Depth     int
615	Code      Code      // "compiled" code
616	Loop      *LoopInfo // != nil when compiling a for or switch
617	Func      *FuncInfo // != nil when compiling a function
618	Labels    map[string]*int
619	Outer     *Comp
620	FuncMaker *funcMaker // used by debugger command 'backtrace' to obtain function name, type and binds for arguments and results
621}
622
623// ================================= Env =================================
624
625type EnvBinds struct {
626	Vals []r.Value
627	Ints []uint64
628}
629
630// Env is the interpreter's runtime environment
631type Env struct {
632	EnvBinds
633	Outer           *Env
634	IP              int
635	Code            []Stmt
636	Run             *Run
637	FileEnv         *Env
638	DebugPos        []token.Pos // for debugging interpreted code: position of each statement
639	DebugComp       *Comp       // for debugging interpreted code: compiler with Binds, and to rebuild an Interp if needed
640	Caller          *Env        // for debugging interpreted code: previous function in call stack. nil for nested *Env
641	CallDepth       int         // for debugging interpreted code: depth of call stack
642	UsedByClosure   bool        // a bitfield would introduce more races among goroutines
643	IntAddressTaken bool        // true if &Env.Ints[index] was executed... then we cannot reuse or reallocate Ints
644}
645
646// ================================= Import =================================
647
648// Import represents an imported package.
649// we cannot name it "Package" because it conflicts with ast2.Package
650type Import struct {
651	// model as a combination of CompBinds and EnvBinds, because to support the command 'package PATH'
652	// we must convert Comp+Env to Import and vice-versa.
653	// This has the added benefit of allowing packages to freely mix
654	// interpreted and compiled constants, functions, variables and types.
655	CompBinds
656	*EnvBinds
657	env *Env
658}
659