/
nil_props.go
128 lines (120 loc) · 3.5 KB
/
nil_props.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
121
122
123
124
125
126
127
128
package props
import (
"github.com/Syuparn/pangaea/object"
)
// NilProps provides built-in props for Nil.
// NOTE: Some Nil props are defind by native code (not by this function).
func NilProps(propContainer map[string]object.PanObject) map[string]object.PanObject {
// NOTE: inject some built-in functions which relate to parser or evaluator
return map[string]object.PanObject{
"==": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
if len(args) < 2 {
return object.NewTypeErr("== requires at least 2 args")
}
if _, ok := object.TraceProtoOfNil(args[0]); !ok {
return object.BuiltInFalse
}
if _, ok := object.TraceProtoOfNil(args[1]); !ok {
return object.BuiltInFalse
}
return object.BuiltInTrue
},
),
"+": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
// anything can be added to nil (and nil works as zero value).
if len(args) < 2 {
return object.NewTypeErr("+ requires at least 2 args")
}
return args[1]
},
),
"-": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
// anything can be subtracted from nil (and nil works as zero value).
if len(args) < 2 {
return object.NewTypeErr("- requires at least 2 args")
}
// return -args[1]
return propContainer["Obj_callProp"].(*object.PanBuiltIn).Fn(
env, object.EmptyPanObjPtr(),
object.EmptyPanObjPtr(), args[1], prefixMinusSym,
)
},
),
"*": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
// anything can be multiplied by nil (and nil works as identity unit (1 for example)).
if len(args) < 2 {
return object.NewTypeErr("* requires at least 2 args")
}
return args[1]
},
),
"/": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
// anything can be divided by nil (and nil works as 1).
if len(args) < 2 {
return object.NewTypeErr("/ requires at least 2 args")
}
// return 1 / args[1]
return propContainer["Obj_callProp"].(*object.PanBuiltIn).Fn(
env, object.EmptyPanObjPtr(),
object.EmptyPanObjPtr(), object.NewPanInt(1), divSym, args[1],
)
},
),
"//": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
// anything can be divided by nil (and nil works as 1).
if len(args) < 2 {
return object.NewTypeErr("// requires at least 2 args")
}
// return 1 / args[1]
return propContainer["Obj_callProp"].(*object.PanBuiltIn).Fn(
env, object.EmptyPanObjPtr(),
object.EmptyPanObjPtr(), object.NewPanInt(1), floorDivSym, args[1],
)
},
),
"_name": object.NewPanStr("Nil"),
"B": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
if len(args) < 1 {
return object.NewTypeErr("Nil#B requires at least 1 arg")
}
_, ok := object.TraceProtoOfNil(args[0])
if !ok {
return object.NewTypeErr(`\1 must be nil`)
}
return object.BuiltInFalse
},
),
"new": f(
func(
env *object.Env, kwargs *object.PanObj, args ...object.PanObject,
) object.PanObject {
if len(args) < 1 {
return object.NewTypeErr("Nil#bear requires at least 1 arg")
}
// NOTE: Nil's descendants also call this
return object.NewInheritedNil(args[0])
},
),
}
}