1// Copyright 2017 The Wuffs Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15//go:generate go run gen.go 16 17package check 18 19import ( 20 "fmt" 21 22 "github.com/google/wuffs/lang/builtin" 23 "github.com/google/wuffs/lang/parse" 24 25 a "github.com/google/wuffs/lang/ast" 26 t "github.com/google/wuffs/lang/token" 27) 28 29var ( 30 exprArgs = a.NewExpr(0, 0, 0, t.IDArgs, nil, nil, nil, nil) 31 exprNullptr = a.NewExpr(0, 0, 0, t.IDNullptr, nil, nil, nil, nil) 32 exprThis = a.NewExpr(0, 0, 0, t.IDThis, nil, nil, nil, nil) 33) 34 35var ( 36 typeExprGeneric1 = a.NewTypeExpr(0, t.IDBase, t.IDDagger1, nil, nil, nil) 37 typeExprGeneric2 = a.NewTypeExpr(0, t.IDBase, t.IDDagger2, nil, nil, nil) 38 typeExprIdeal = a.NewTypeExpr(0, t.IDBase, t.IDQIdeal, nil, nil, nil) 39 typeExprList = a.NewTypeExpr(0, t.IDBase, t.IDComma, nil, nil, nil) 40 typeExprNullptr = a.NewTypeExpr(0, t.IDBase, t.IDQNullptr, nil, nil, nil) 41 typeExprPlaceholder = a.NewTypeExpr(0, t.IDBase, t.IDQPlaceholder, nil, nil, nil) 42 typeExprTypeExpr = a.NewTypeExpr(0, t.IDBase, t.IDQTypeExpr, nil, nil, nil) 43 44 typeExprU8 = a.NewTypeExpr(0, t.IDBase, t.IDU8, nil, nil, nil) 45 typeExprU16 = a.NewTypeExpr(0, t.IDBase, t.IDU16, nil, nil, nil) 46 typeExprU32 = a.NewTypeExpr(0, t.IDBase, t.IDU32, nil, nil, nil) 47 typeExprU64 = a.NewTypeExpr(0, t.IDBase, t.IDU64, nil, nil, nil) 48 49 typeExprEmptyStruct = a.NewTypeExpr(0, t.IDBase, t.IDEmptyStruct, nil, nil, nil) 50 typeExprBool = a.NewTypeExpr(0, t.IDBase, t.IDBool, nil, nil, nil) 51 typeExprUtility = a.NewTypeExpr(0, t.IDBase, t.IDUtility, nil, nil, nil) 52 53 typeExprRangeIEU32 = a.NewTypeExpr(0, t.IDBase, t.IDRangeIEU32, nil, nil, nil) 54 typeExprRangeIIU32 = a.NewTypeExpr(0, t.IDBase, t.IDRangeIIU32, nil, nil, nil) 55 typeExprRangeIEU64 = a.NewTypeExpr(0, t.IDBase, t.IDRangeIEU64, nil, nil, nil) 56 typeExprRangeIIU64 = a.NewTypeExpr(0, t.IDBase, t.IDRangeIIU64, nil, nil, nil) 57 typeExprRectIEU32 = a.NewTypeExpr(0, t.IDBase, t.IDRectIEU32, nil, nil, nil) 58 typeExprRectIIU32 = a.NewTypeExpr(0, t.IDBase, t.IDRectIIU32, nil, nil, nil) 59 60 typeExprIOReader = a.NewTypeExpr(0, t.IDBase, t.IDIOReader, nil, nil, nil) 61 typeExprIOWriter = a.NewTypeExpr(0, t.IDBase, t.IDIOWriter, nil, nil, nil) 62 typeExprStatus = a.NewTypeExpr(0, t.IDBase, t.IDStatus, nil, nil, nil) 63 64 typeExprFrameConfig = a.NewTypeExpr(0, t.IDBase, t.IDFrameConfig, nil, nil, nil) 65 typeExprImageConfig = a.NewTypeExpr(0, t.IDBase, t.IDImageConfig, nil, nil, nil) 66 typeExprPixelBuffer = a.NewTypeExpr(0, t.IDBase, t.IDPixelBuffer, nil, nil, nil) 67 typeExprPixelConfig = a.NewTypeExpr(0, t.IDBase, t.IDPixelConfig, nil, nil, nil) 68 typeExprPixelSwizzler = a.NewTypeExpr(0, t.IDBase, t.IDPixelSwizzler, nil, nil, nil) 69 70 typeExprDecodeFrameOptions = a.NewTypeExpr(0, t.IDBase, t.IDDecodeFrameOptions, nil, nil, nil) 71 72 typeExprSliceU8 = a.NewTypeExpr(t.IDSlice, 0, 0, nil, nil, typeExprU8) 73 typeExprTableU8 = a.NewTypeExpr(t.IDTable, 0, 0, nil, nil, typeExprU8) 74) 75 76func setPlaceholderMBoundsMType(n *a.Node) { 77 n.SetMBounds(bounds{zero, zero}) 78 n.SetMType(typeExprPlaceholder) 79} 80 81// typeMap maps from variable names (as token IDs) to types. 82type typeMap map[t.ID]*a.TypeExpr 83 84var builtInTypeMap = typeMap{ 85 t.IDU8: typeExprU8, 86 t.IDU16: typeExprU16, 87 t.IDU32: typeExprU32, 88 t.IDU64: typeExprU64, 89 90 t.IDEmptyStruct: typeExprEmptyStruct, 91 t.IDBool: typeExprBool, 92 t.IDUtility: typeExprUtility, 93 94 t.IDRangeIEU32: typeExprRangeIEU32, 95 t.IDRangeIIU32: typeExprRangeIIU32, 96 t.IDRangeIEU64: typeExprRangeIEU64, 97 t.IDRangeIIU64: typeExprRangeIIU64, 98 t.IDRectIEU32: typeExprRectIEU32, 99 t.IDRectIIU32: typeExprRectIIU32, 100 101 t.IDIOReader: typeExprIOReader, 102 t.IDIOWriter: typeExprIOWriter, 103 t.IDStatus: typeExprStatus, 104 105 t.IDFrameConfig: typeExprFrameConfig, 106 t.IDImageConfig: typeExprImageConfig, 107 t.IDPixelBuffer: typeExprPixelBuffer, 108 t.IDPixelConfig: typeExprPixelConfig, 109 t.IDPixelSwizzler: typeExprPixelSwizzler, 110 111 t.IDDecodeFrameOptions: typeExprDecodeFrameOptions, 112} 113 114func (c *Checker) parseBuiltInFuncs(ss []string, generic bool) (map[t.QQID]*a.Func, error) { 115 m := map[t.QQID]*a.Func(nil) 116 if generic { 117 m = map[t.QQID]*a.Func{} 118 } 119 120 buf := []byte(nil) 121 for _, s := range ss { 122 buf = buf[:0] 123 buf = append(buf, "pub func "...) 124 buf = append(buf, s...) 125 buf = append(buf, "{}\n"...) 126 127 const filename = "builtin.wuffs" 128 tokens, _, err := t.Tokenize(c.tm, filename, buf) 129 if err != nil { 130 return nil, fmt.Errorf("check: parsing %q: could not tokenize built-in funcs: %v", s, err) 131 } 132 if generic { 133 for i := range tokens { 134 if tokens[i].ID == builtin.GenericOldName1 { 135 tokens[i].ID = builtin.GenericNewName1 136 } else if tokens[i].ID == builtin.GenericOldName2 { 137 tokens[i].ID = builtin.GenericNewName2 138 } 139 } 140 } 141 file, err := parse.Parse(c.tm, filename, tokens, &parse.Options{ 142 AllowBuiltInNames: true, 143 }) 144 if err != nil { 145 return nil, fmt.Errorf("check: parsing %q: could not parse built-in funcs: %v", s, err) 146 } 147 148 tlds := file.TopLevelDecls() 149 if len(tlds) != 1 || tlds[0].Kind() != a.KFunc { 150 return nil, fmt.Errorf("check: parsing %q: got %d top level decls, want %d", s, len(tlds), 1) 151 } 152 f := tlds[0].AsFunc() 153 f.AsNode().AsRaw().SetPackage(c.tm, t.IDBase) 154 if err := c.checkFuncSignature(f.AsNode()); err != nil { 155 return nil, err 156 } 157 158 if m != nil { 159 m[f.QQID()] = f 160 } 161 } 162 return m, nil 163} 164 165func (c *Checker) resolveFunc(typ *a.TypeExpr) (*a.Func, error) { 166 if typ.Decorator() != t.IDFunc { 167 return nil, fmt.Errorf("check: resolveFunc cannot look up non-func TypeExpr %q", typ.Str(c.tm)) 168 } 169 lTyp := typ.Receiver() 170 lQID := lTyp.QID() 171 qqid := t.QQID{lQID[0], lQID[1], typ.FuncName()} 172 173 if lTyp.IsSliceType() { 174 qqid[0] = t.IDBase 175 qqid[1] = t.IDDagger1 176 if f := c.builtInSliceFuncs[qqid]; f != nil { 177 return f, nil 178 } 179 180 } else if lTyp.IsTableType() { 181 qqid[0] = t.IDBase 182 qqid[1] = t.IDDagger2 183 if f := c.builtInTableFuncs[qqid]; f != nil { 184 return f, nil 185 } 186 187 } else if f := c.funcs[qqid]; f != nil { 188 return f, nil 189 } 190 return nil, fmt.Errorf("check: resolveFunc cannot look up %q", typ.Str(c.tm)) 191} 192