tc_universe.mx raw
1 package main
2
3 // Universe is the outermost scope containing all predeclared identifiers.
4 // All package scopes have Universe as their ultimate ancestor.
5 var Universe *Scope
6
7 // Predeclared types. Indices match BasicKind values.
8 var Typ [UntypedNil + 1]*Basic
9
10 var universeError *TypeName
11
12 func initUniverse() {
13 if Universe != nil {
14 return
15 }
16 Universe = NewScope(nil)
17
18 // Initialize Basic types in Typ table.
19 infos := [...]struct {
20 kind BasicKind
21 info BasicInfo
22 name string
23 }{
24 {Invalid, 0, "invalid type"},
25
26 {Bool, IsBoolean, "bool"},
27
28 {Int8, IsInteger | IsOrdered | IsNumeric, "int8"},
29 {Int16, IsInteger | IsOrdered | IsNumeric, "int16"},
30 {Int32, IsInteger | IsOrdered | IsNumeric, "int32"},
31 {Int64, IsInteger | IsOrdered | IsNumeric, "int64"},
32 {Uint8, IsInteger | IsUnsigned | IsOrdered | IsNumeric, "uint8"},
33 {Uint16, IsInteger | IsUnsigned | IsOrdered | IsNumeric, "uint16"},
34 {Uint32, IsInteger | IsUnsigned | IsOrdered | IsNumeric, "uint32"},
35 {Uint64, IsInteger | IsUnsigned | IsOrdered | IsNumeric, "uint64"},
36
37 {Float32, IsFloat | IsOrdered | IsNumeric, "float32"},
38 {Float64, IsFloat | IsOrdered | IsNumeric, "float64"},
39
40 // string and []byte share kind TCString in Moxie.
41 {TCString, IsString | IsOrdered, "string"},
42
43 {UnsafePointer, 0, "Pointer"}, // lives in unsafe package
44
45 {UntypedBool, IsBoolean | IsUntyped, "untyped bool"},
46 {UntypedInt, IsInteger | IsNumeric | IsUntyped, "untyped int"},
47 {UntypedRune, IsInteger | IsNumeric | IsUntyped, "untyped rune"},
48 {UntypedFloat, IsFloat | IsNumeric | IsUntyped, "untyped float"},
49 {UntypedString, IsString | IsUntyped, "untyped string"},
50 {UntypedNil, IsUntyped, "untyped nil"},
51 }
52 for i, info := range infos {
53 Typ[i] = &Basic{kind: info.kind, info: info.info, name: info.name}
54 }
55
56 // In Moxie, int = int32 and uint = uint32. We expose "int" and "uint"
57 // as named aliases to int32/uint32 in the universe scope.
58 defTypeName("bool", Typ[Bool])
59 defTypeName("int8", Typ[Int8])
60 defTypeName("int16", Typ[Int16])
61 defTypeName("int32", Typ[Int32])
62 defTypeName("int64", Typ[Int64])
63 defTypeName("uint8", Typ[Uint8])
64 defTypeName("uint16", Typ[Uint16])
65 defTypeName("uint32", Typ[Uint32])
66 defTypeName("uint64", Typ[Uint64])
67 defTypeName("float32", Typ[Float32])
68 defTypeName("float64", Typ[Float64])
69 defTypeName("string", Typ[TCString])
70
71 // int = int32, uint = uint32 (Moxie always 32-bit)
72 intType := NewNamed(NewTypeName(nil, "int", nil), Typ[Int32])
73 uintType := NewNamed(NewTypeName(nil, "uint", nil), Typ[Uint32])
74 defObj(intType.obj)
75 defObj(uintType.obj)
76 intType.obj.typ = intType
77 uintType.obj.typ = uintType
78
79 // byte = uint8
80 byteType := NewNamed(NewTypeName(nil, "byte", nil), Typ[Uint8])
81 defObj(byteType.obj)
82 byteType.obj.typ = byteType
83
84 // rune = int32
85 runeType := NewNamed(NewTypeName(nil, "rune", nil), Typ[Int32])
86 defObj(runeType.obj)
87 runeType.obj.typ = runeType
88
89 // uintptr (allowed only with import "unsafe")
90 uintptrType := NewNamed(NewTypeName(nil, "uintptr", nil), Typ[Uint64])
91 defObj(uintptrType.obj)
92 uintptrType.obj.typ = uintptrType
93
94 // error interface
95 errMeth := &IfaceMethod{name: "Error", sig: NewSignature(nil, nil, NewTuple(NewTCVar(nil, "", Typ[TCString])), false)}
96 errIface := NewTCInterface([]*IfaceMethod{errMeth}, nil)
97 errIface.Complete()
98 universeError = NewTypeName(nil, "error", errIface)
99 defObj(universeError)
100
101 // complex64/128 are not valid in Moxie programs but appear in stdlib source.
102 // Register them as invalid basic types so the checker doesn't report "undefined".
103 complex64Type := NewNamed(NewTypeName(nil, "complex64", nil), Typ[Invalid])
104 defObj(complex64Type.obj)
105 complex128Type := NewNamed(NewTypeName(nil, "complex128", nil), Typ[Invalid])
106 defObj(complex128Type.obj)
107
108 // any is an alias for interface{} (Go 1.18+)
109 anyIface := NewTCInterface(nil, nil)
110 anyIface.Complete()
111 anyObj := NewTypeName(nil, "any", anyIface)
112 defObj(anyObj)
113
114 // comparable is a builtin interface satisfied by comparable types.
115 comparableIface := NewTCInterface(nil, nil)
116 comparableIface.Complete()
117 comparableObj := NewTypeName(nil, "comparable", comparableIface)
118 defObj(comparableObj)
119
120 // predeclared constants
121 defConst("true", Typ[UntypedBool], untypedBool(true))
122 defConst("false", Typ[UntypedBool], untypedBool(false))
123 defConst("iota", Typ[UntypedInt], untypedInt(0))
124 defNil()
125
126 // predeclared builtins
127 builtinNames := [17]string{
128 BuiltinAppend: "append",
129 BuiltinCap: "cap",
130 BuiltinClear: "clear",
131 BuiltinClose: "close",
132 BuiltinComplex: "complex",
133 BuiltinCopy: "copy",
134 BuiltinDelete: "delete",
135 BuiltinImag: "imag",
136 BuiltinLen: "len",
137 BuiltinMake: "make",
138 BuiltinNew: "new",
139 BuiltinPanic: "panic",
140 BuiltinPrint: "print",
141 BuiltinPrintln: "println",
142 BuiltinReal: "real",
143 BuiltinRecover: "recover",
144 BuiltinSpawn: "spawn",
145 }
146 for id, name := range builtinNames {
147 Universe.Insert(newBuiltin(name, BuiltinID(id)))
148 }
149
150 // Go 1.21 builtins.
151 Universe.Insert(newBuiltin("min", BuiltinMin))
152 Universe.Insert(newBuiltin("max", BuiltinMax))
153 }
154
155 func defTypeName(name string, typ Type) {
156 tn := NewTypeName(nil, name, typ)
157 Universe.Insert(tn)
158 }
159
160 func defObj(obj Object) {
161 Universe.Insert(obj)
162 }
163
164 func defConst(name string, typ Type, val ConstVal) {
165 Universe.Insert(NewTCConst(nil, name, typ, val))
166 }
167
168 func defNil() {
169 Universe.Insert(NewTCConst(nil, "nil", Typ[UntypedNil], untypedNil()))
170 }
171
172 // Placeholder constant values. These wrap go/constant values. In B4 they
173 // become native Moxie values.
174 type constBool struct{ v bool }
175 type constInt struct{ v int64 }
176 type constNil struct{}
177
178 func untypedBool(v bool) ConstVal { return constBool{v} }
179 func untypedInt(v int64) ConstVal { return constInt{v} }
180 func untypedNil() ConstVal { return constNil{} }
181
182 func (c constBool) String() string { if c.v { return "true" }; return "false" }
183 func (c constInt) String() string {
184 n := c.v
185 if n == 0 {
186 return "0"
187 }
188 neg := n < 0
189 if neg {
190 n = -n
191 }
192 buf := []byte{:0:20}
193 for n > 0 {
194 buf = append(buf, byte('0'+n%10))
195 n /= 10
196 }
197 if neg {
198 buf = append(buf, '-')
199 }
200 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
201 buf[i], buf[j] = buf[j], buf[i]
202 }
203 return string(buf)
204 }
205 func (c constNil) String() string { return "nil" }
206
207 // Predeclared returns the universe-scope object with the given name, or nil.
208 func Predeclared(name string) Object {
209 return Universe.Lookup(name)
210 }
211