-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunction.go
102 lines (93 loc) · 2.03 KB
/
function.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
package vesper
import "fmt"
// Apply is a primitive instruction to apply a function to a list of arguments
var Apply = &Object{Type: FunctionType}
// CallCC is a primitive instruction to executable (restore) a continuation
var CallCC = &Object{Type: FunctionType}
// GoFunc is a primitive instruction to create a goroutine
var GoFunc = &Object{Type: FunctionType}
// IsFunction returns true if the object is a function
func IsFunction(obj *Object) bool {
return obj.Type == FunctionType
}
// Closure creates a new closure in the given frame
func Closure(code *Code, frame *frame) *Object {
return &Object{
Type: FunctionType,
code: code,
frame: frame,
}
}
func functionToString(f *Object) string {
if f.primitive != nil {
return "#[function " + f.primitive.name + "]"
}
if f.code != nil {
n := f.code.name
if n == "" {
return "#[function]"
}
return fmt.Sprintf("#[function %s]", n)
}
if f.continuation != nil {
return "#[continuation]"
}
if f == Apply {
return "#[function apply]"
}
if f == CallCC {
return "#[function callcc]"
}
if f == GoFunc {
return "#[function go]"
}
return "#[invalid function]"
}
func functionSignature(f *Object) string {
if f.primitive != nil {
return f.primitive.signature
}
if f.code != nil {
return f.code.signature()
}
if f.continuation != nil {
return "(<function>) <any>"
}
if f == Apply {
return "(<any>*) <list>"
}
if f == CallCC {
return "(<function>) <any>"
}
if f == GoFunc {
return "(<function> <any>*) <null>"
}
return "(<invalidfunction>) <invalid>"
}
func functionSignatureFromTypes(result *Object, args []*Object, rest *Object) string {
sig := "("
for i, t := range args {
if !IsType(t) {
return ("not a type: " + t.String())
}
if i > 0 {
sig += " "
}
sig += t.text
}
if rest != nil {
if !IsType(rest) {
return ("not a type: " + rest.String())
}
if sig != "(" {
sig += " "
}
sig += rest.text + "*"
}
sig += ") "
if !IsType(result) {
return ("not a type: " + result.String())
}
sig += result.text
return sig
}