• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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