forked from elves/elvish
/
source.go
120 lines (102 loc) · 2.53 KB
/
source.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package eval
import (
"fmt"
"strconv"
"github.com/elves/elvish/eval/vals"
"github.com/elves/elvish/parse"
"github.com/xiaq/persistent/hash"
)
// Source describes a piece of source code.
type Source struct {
typ SrcType
name string
path string
code string
}
// NewInteractiveSource returns a Source for a piece of code entered
// interactively.
func NewInteractiveSource(code string) *Source {
return &Source{SrcInteractive, "", "", code}
}
// NewScriptSource returns a Source for a piece of code used as a script.
func NewScriptSource(name, path, code string) *Source {
return &Source{SrcScript, name, path, code}
}
// NewModuleSource returns a Source for a piece of code used as a module.
func NewModuleSource(name, path, code string) *Source {
return &Source{SrcModule, name, path, code}
}
func NewInternalSource(name string) *Source {
return &Source{SrcInternal, name, name, ""}
}
func (src *Source) describePath() string {
if src.typ == SrcInteractive {
return "[tty]"
}
return src.path
}
var (
_ vals.Indexer = (*Source)(nil)
)
func (src *Source) Kind() string {
return "map"
}
func (src *Source) Hash() uint32 {
return hash.DJB(uint32(src.typ),
hash.String(src.name), hash.String(src.path), hash.String(src.code))
}
func (src *Source) Equal(other interface{}) bool {
if src2, ok := other.(*Source); ok {
return *src == *src2
}
return false
}
func (src *Source) Repr(int) string {
return fmt.Sprintf("<src type:%s name:%s path:%s code:...>",
src.typ, parse.Quote(src.name), parse.Quote(src.path))
}
func (src *Source) Index(k interface{}) (interface{}, bool) {
ret := ""
switch k {
case "type":
ret = src.typ.String()
case "name":
ret = src.name
case "path":
ret = src.path
case "code":
ret = src.code
default:
return nil, false
}
return ret, true
}
func (src *Source) IterateKeys(f func(interface{}) bool) {
vals.Feed(f, "type", "name", "path", "code")
}
// SrcType records the type of a piece of source code.
type SrcType int
const (
// SrcInternal is a special SrcType for internal operations.
SrcInternal SrcType = iota
// SrcInteractive is the type of source code entered interactively.
SrcInteractive
// SrcScript is the type of source code used as a script.
SrcScript
// SrcModule is the type of source code used as a module.
SrcModule
)
func (t SrcType) String() string {
switch t {
case SrcInternal:
return "internal"
case SrcInteractive:
return "interactive"
case SrcScript:
return "script"
case SrcModule:
return "module"
default:
return "bad type " + strconv.Itoa(int(t))
}
}