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