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