• 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
15package ast
16
17import (
18	t "github.com/google/wuffs/lang/token"
19)
20
21// Str returns a string form of n.
22func (n *Expr) Str(tm *t.Map) string {
23	if n == nil {
24		return ""
25	}
26	if n.id0 == 0 && n.id1 == 0 {
27		return tm.ByID(n.id2)
28	}
29	return string(n.appendStr(nil, tm, false, 0))
30}
31
32func (n *Expr) appendStr(buf []byte, tm *t.Map, parenthesize bool, depth uint32) []byte {
33	if depth > MaxExprDepth {
34		return append(buf, "!expr_recursion_depth_too_large!"...)
35	}
36	depth++
37
38	if n == nil {
39		return buf
40	}
41
42	if n.id0.IsXOp() {
43		switch {
44		case n.id0.IsXUnaryOp():
45			buf = append(buf, opString(n.id0)...)
46			buf = n.rhs.AsExpr().appendStr(buf, tm, true, depth)
47
48		case n.id0.IsXBinaryOp():
49			if parenthesize {
50				buf = append(buf, '(')
51			}
52			buf = n.lhs.AsExpr().appendStr(buf, tm, true, depth)
53			buf = append(buf, opString(n.id0)...)
54			if n.id0 == t.IDXBinaryAs {
55				buf = append(buf, n.rhs.AsTypeExpr().Str(tm)...)
56			} else {
57				buf = n.rhs.AsExpr().appendStr(buf, tm, true, depth)
58			}
59			if parenthesize {
60				buf = append(buf, ')')
61			}
62
63		case n.id0.IsXAssociativeOp():
64			if parenthesize {
65				buf = append(buf, '(')
66			}
67			op := opString(n.id0)
68			for i, o := range n.list0 {
69				if i != 0 {
70					buf = append(buf, op...)
71				}
72				buf = o.AsExpr().appendStr(buf, tm, true, depth)
73			}
74			if parenthesize {
75				buf = append(buf, ')')
76			}
77		}
78
79	} else {
80		switch n.id0 {
81		case 0:
82			if n.id1 != 0 {
83				buf = append(buf, tm.ByID(n.id1)...)
84				buf = append(buf, '.')
85			}
86			buf = append(buf, tm.ByID(n.id2)...)
87
88		case t.IDOpenParen:
89			buf = n.lhs.AsExpr().appendStr(buf, tm, true, depth)
90			buf = append(buf, n.flags.AsEffect().String()...)
91			buf = append(buf, '(')
92			for i, o := range n.list0 {
93				if i != 0 {
94					buf = append(buf, ", "...)
95				}
96				buf = append(buf, tm.ByID(o.AsArg().Name())...)
97				buf = append(buf, ':')
98				buf = o.AsArg().Value().appendStr(buf, tm, false, depth)
99			}
100			buf = append(buf, ')')
101
102		case t.IDOpenBracket:
103			buf = n.lhs.AsExpr().appendStr(buf, tm, true, depth)
104			buf = append(buf, '[')
105			buf = n.rhs.AsExpr().appendStr(buf, tm, false, depth)
106			buf = append(buf, ']')
107
108		case t.IDColon:
109			buf = n.lhs.AsExpr().appendStr(buf, tm, true, depth)
110			buf = append(buf, '[')
111			buf = n.mhs.AsExpr().appendStr(buf, tm, false, depth)
112			buf = append(buf, ':')
113			buf = n.rhs.AsExpr().appendStr(buf, tm, false, depth)
114			buf = append(buf, ']')
115
116		case t.IDDot:
117			buf = n.lhs.AsExpr().appendStr(buf, tm, true, depth)
118			buf = append(buf, '.')
119			buf = append(buf, tm.ByID(n.id2)...)
120
121		case t.IDComma:
122			buf = append(buf, '[')
123			for i, o := range n.list0 {
124				if i != 0 {
125					buf = append(buf, ", "...)
126				}
127				buf = o.AsExpr().appendStr(buf, tm, false, depth)
128			}
129			buf = append(buf, ']')
130		}
131	}
132
133	return buf
134}
135
136func opString(x t.ID) string {
137	if x < t.ID(len(opStrings)) {
138		if s := opStrings[x]; s != "" {
139			return s
140		}
141	}
142	return " no_such_Wuffs_operator "
143}
144
145var opStrings = [...]string{
146	t.IDXUnaryPlus:  "+",
147	t.IDXUnaryMinus: "-",
148	t.IDXUnaryNot:   "not ",
149	t.IDXUnaryRef:   "ref ",
150	t.IDXUnaryDeref: "deref ",
151
152	t.IDXBinaryPlus:           " + ",
153	t.IDXBinaryMinus:          " - ",
154	t.IDXBinaryStar:           " * ",
155	t.IDXBinarySlash:          " / ",
156	t.IDXBinaryShiftL:         " << ",
157	t.IDXBinaryShiftR:         " >> ",
158	t.IDXBinaryAmp:            " & ",
159	t.IDXBinaryPipe:           " | ",
160	t.IDXBinaryHat:            " ^ ",
161	t.IDXBinaryPercent:        " % ",
162	t.IDXBinaryTildeModShiftL: " ~mod<< ",
163	t.IDXBinaryTildeModPlus:   " ~mod+ ",
164	t.IDXBinaryTildeModMinus:  " ~mod- ",
165	t.IDXBinaryTildeSatPlus:   " ~sat+ ",
166	t.IDXBinaryTildeSatMinus:  " ~sat- ",
167	t.IDXBinaryNotEq:          " <> ",
168	t.IDXBinaryLessThan:       " < ",
169	t.IDXBinaryLessEq:         " <= ",
170	t.IDXBinaryEqEq:           " == ",
171	t.IDXBinaryGreaterEq:      " >= ",
172	t.IDXBinaryGreaterThan:    " > ",
173	t.IDXBinaryAnd:            " and ",
174	t.IDXBinaryOr:             " or ",
175	t.IDXBinaryAs:             " as ",
176
177	t.IDXAssociativePlus: " + ",
178	t.IDXAssociativeStar: " * ",
179	t.IDXAssociativeAmp:  " & ",
180	t.IDXAssociativePipe: " | ",
181	t.IDXAssociativeHat:  " ^ ",
182	t.IDXAssociativeAnd:  " and ",
183	t.IDXAssociativeOr:   " or ",
184}
185
186// Str returns a string form of n.
187func (n *TypeExpr) Str(tm *t.Map) string {
188	if n == nil {
189		return ""
190	}
191	if n.Decorator() == 0 && n.Min() == nil && n.Max() == nil {
192		return n.QID().Str(tm)
193	}
194	return string(n.appendStr(nil, tm, 0))
195}
196
197func (n *TypeExpr) appendStr(buf []byte, tm *t.Map, depth uint32) []byte {
198	if depth > MaxTypeExprDepth {
199		return append(buf, "!type_expr_recursion_depth_too_large!"...)
200	}
201	depth++
202	if n == nil {
203		return append(buf, "!invalid_type!"...)
204	}
205
206	switch n.Decorator() {
207	case 0:
208		buf = append(buf, n.QID().Str(tm)...)
209	case t.IDNptr:
210		buf = append(buf, "nptr "...)
211		return n.Inner().appendStr(buf, tm, depth)
212	case t.IDPtr:
213		buf = append(buf, "ptr "...)
214		return n.Inner().appendStr(buf, tm, depth)
215	case t.IDArray:
216		buf = append(buf, "array["...)
217		buf = n.ArrayLength().appendStr(buf, tm, false, 0)
218		buf = append(buf, "] "...)
219		return n.Inner().appendStr(buf, tm, depth)
220	case t.IDSlice:
221		buf = append(buf, "slice "...)
222		return n.Inner().appendStr(buf, tm, depth)
223	case t.IDTable:
224		buf = append(buf, "table "...)
225		return n.Inner().appendStr(buf, tm, depth)
226	case t.IDFunc:
227		buf = append(buf, "func "...)
228		if r := n.Receiver(); r != nil {
229			buf = append(buf, '(')
230			buf = r.appendStr(buf, tm, depth)
231			buf = append(buf, ")."...)
232		}
233		return append(buf, n.FuncName().Str(tm)...)
234	default:
235		return append(buf, "!invalid_type!"...)
236	}
237	if n.Min() != nil || n.Max() != nil {
238		buf = append(buf, '[')
239		buf = n.Min().appendStr(buf, tm, false, 0)
240		buf = append(buf, ".."...)
241		buf = n.Max().appendStr(buf, tm, false, 0)
242		buf = append(buf, ']')
243	}
244	return buf
245}
246