1// Copyright 2018 The OPA Authors. All rights reserved. 2// Use of this source code is governed by an Apache2 3// license that can be found in the LICENSE file.op 4 5package ast 6 7import ( 8 "bytes" 9 "encoding/json" 10 "fmt" 11 "math/big" 12) 13 14const ( 15 // commentsKey is the global map key for the comments slice. 16 commentsKey = "comments" 17 18 // filenameKey is the global map key for the filename. 19 filenameKey = "filename" 20) 21 22type program struct { 23 buf []interface{} 24 comments interface{} 25} 26 27type ruleExt struct { 28 loc *Location 29 term *Term 30 body Body 31} 32 33// currentLocation converts the parser context to a Location object. 34func currentLocation(c *current) *Location { 35 return NewLocation(c.text, c.globalStore[filenameKey].(string), c.pos.line, c.pos.col) 36} 37 38func makeProgram(c *current, vals interface{}) (interface{}, error) { 39 var buf []interface{} 40 if vals == nil { 41 return buf, nil 42 } 43 ifaceSlice := vals.([]interface{}) 44 head := ifaceSlice[0] 45 buf = append(buf, head) 46 for _, tail := range ifaceSlice[1].([]interface{}) { 47 stmt := tail.([]interface{})[1] 48 buf = append(buf, stmt) 49 } 50 return program{buf, c.globalStore[commentsKey]}, nil 51} 52 53func makePackage(loc *Location, value interface{}) (interface{}, error) { 54 // All packages are implicitly declared under the default root document. 55 term := value.(*Term) 56 path := Ref{DefaultRootDocument.Copy().SetLocation(term.Location)} 57 switch v := term.Value.(type) { 58 case Ref: 59 // Convert head of package Ref to String because it will be prefixed 60 // with the root document variable. 61 head := StringTerm(string(v[0].Value.(Var))).SetLocation(v[0].Location) 62 tail := v[1:] 63 if !tail.IsGround() { 64 return nil, fmt.Errorf("package name cannot contain variables: %v", v) 65 } 66 67 // We do not allow non-string values in package names. 68 // Because documents are typically represented as JSON, non-string keys are 69 // not allowed for now. 70 // TODO(tsandall): consider special syntax for namespacing under arrays. 71 for _, p := range tail { 72 _, ok := p.Value.(String) 73 if !ok { 74 return nil, fmt.Errorf("package name cannot contain non-string values: %v", v) 75 } 76 } 77 path = append(path, head) 78 path = append(path, tail...) 79 case Var: 80 s := StringTerm(string(v)).SetLocation(term.Location) 81 path = append(path, s) 82 } 83 pkg := &Package{Location: loc, Path: path} 84 return pkg, nil 85} 86 87func makeImport(loc *Location, path, alias interface{}) (interface{}, error) { 88 imp := &Import{} 89 imp.Location = loc 90 imp.Path = path.(*Term) 91 if err := IsValidImportPath(imp.Path.Value); err != nil { 92 return nil, err 93 } 94 if alias == nil { 95 return imp, nil 96 } 97 aliasSlice := alias.([]interface{}) 98 // Import definition above describes the "alias" slice. We only care about the "Var" element. 99 imp.Alias = aliasSlice[3].(*Term).Value.(Var) 100 return imp, nil 101} 102 103func makeDefaultRule(loc *Location, name, value interface{}) (interface{}, error) { 104 105 term := value.(*Term) 106 var err error 107 108 vis := NewGenericVisitor(func(x interface{}) bool { 109 if err != nil { 110 return true 111 } 112 switch x.(type) { 113 case *ArrayComprehension, *ObjectComprehension, *SetComprehension: // skip closures 114 return true 115 case Ref, Var: 116 err = fmt.Errorf("default rule value cannot contain %v", TypeName(x)) 117 return true 118 } 119 return false 120 }) 121 122 Walk(vis, term) 123 124 if err != nil { 125 return nil, err 126 } 127 128 body := NewBody(NewExpr(BooleanTerm(true).SetLocation(loc))) 129 130 rule := &Rule{ 131 Location: loc, 132 Default: true, 133 Head: &Head{ 134 Location: loc, 135 Name: name.(*Term).Value.(Var), 136 Value: value.(*Term), 137 }, 138 Body: body, 139 } 140 rule.Body[0].Location = loc 141 142 return []*Rule{rule}, nil 143} 144 145func makeRule(loc *Location, head, rest interface{}) (interface{}, error) { 146 147 if head == nil { 148 return nil, nil 149 } 150 151 sl := rest.([]interface{}) 152 153 rules := []*Rule{ 154 { 155 Location: loc, 156 Head: head.(*Head), 157 Body: sl[0].(Body), 158 }, 159 } 160 161 var ordered bool 162 prev := rules[0] 163 164 for i, elem := range sl[1].([]interface{}) { 165 166 next := elem.([]interface{}) 167 re := next[1].(ruleExt) 168 169 if re.term == nil { 170 if ordered { 171 return nil, fmt.Errorf("expected 'else' keyword") 172 } 173 rules = append(rules, &Rule{ 174 Location: re.loc, 175 Head: prev.Head.Copy(), 176 Body: re.body, 177 }) 178 } else { 179 if (rules[0].Head.DocKind() != CompleteDoc) || (i != 0 && !ordered) { 180 return nil, fmt.Errorf("unexpected 'else' keyword") 181 } 182 ordered = true 183 curr := &Rule{ 184 Location: re.loc, 185 Head: &Head{ 186 Name: prev.Head.Name, 187 Args: prev.Head.Args.Copy(), 188 Value: re.term, 189 Location: re.term.Location, 190 }, 191 Body: re.body, 192 } 193 prev.Else = curr 194 prev = curr 195 } 196 } 197 198 return rules, nil 199} 200 201func makeRuleHead(loc *Location, name, args, key, value interface{}) (interface{}, error) { 202 203 head := &Head{} 204 205 head.Location = loc 206 head.Name = name.(*Term).Value.(Var) 207 208 if args != nil && key != nil { 209 return nil, fmt.Errorf("partial rules cannot take arguments") 210 } 211 212 if args != nil { 213 argSlice := args.([]interface{}) 214 head.Args = argSlice[3].(Args) 215 } 216 217 if key != nil { 218 keySlice := key.([]interface{}) 219 // Head definition above describes the "key" slice. We care about the "Term" element. 220 head.Key = keySlice[3].(*Term) 221 } 222 223 if value != nil { 224 valueSlice := value.([]interface{}) 225 // Head definition above describes the "value" slice. We care about the "Term" element. 226 head.Value = valueSlice[len(valueSlice)-1].(*Term) 227 } 228 229 if key == nil && value == nil { 230 head.Value = BooleanTerm(true).SetLocation(head.Location) 231 } 232 233 if key != nil && value != nil { 234 switch head.Key.Value.(type) { 235 case Var, String, Ref: // nop 236 default: 237 return nil, fmt.Errorf("object key must be string, var, or ref, not %v", TypeName(head.Key.Value)) 238 } 239 } 240 241 return head, nil 242} 243 244func makeArgs(list interface{}) (interface{}, error) { 245 termSlice := list.([]*Term) 246 args := make(Args, len(termSlice)) 247 for i := 0; i < len(args); i++ { 248 args[i] = termSlice[i] 249 } 250 return args, nil 251} 252 253func makeRuleExt(loc *Location, val, b interface{}) (interface{}, error) { 254 bs := b.([]interface{}) 255 body := bs[1].(Body) 256 257 if val == nil { 258 term := BooleanTerm(true) 259 term.Location = loc 260 return ruleExt{term.Location, term, body}, nil 261 } 262 263 vs := val.([]interface{}) 264 t := vs[3].(*Term) 265 return ruleExt{loc, t, body}, nil 266} 267 268func makeLiteral(negated, value, with interface{}) (interface{}, error) { 269 270 expr := value.(*Expr) 271 272 expr.Negated = negated.(bool) 273 274 if with != nil { 275 expr.With = with.([]*With) 276 } 277 278 return expr, nil 279} 280 281func makeLiteralExpr(loc *Location, lhs, rest interface{}) (interface{}, error) { 282 283 if rest == nil { 284 if call, ok := lhs.(*Term).Value.(Call); ok { 285 return NewExpr([]*Term(call)).SetLocation(loc), nil 286 } 287 return NewExpr(lhs).SetLocation(loc), nil 288 } 289 290 termSlice := rest.([]interface{}) 291 terms := []*Term{ 292 termSlice[1].(*Term), 293 lhs.(*Term), 294 termSlice[3].(*Term), 295 } 296 297 expr := NewExpr(terms).SetLocation(loc) 298 299 return expr, nil 300} 301 302func makeWithKeywordList(head, tail interface{}) (interface{}, error) { 303 var withs []*With 304 305 if head == nil { 306 return withs, nil 307 } 308 309 sl := tail.([]interface{}) 310 311 withs = make([]*With, 0, len(sl)+1) 312 withs = append(withs, head.(*With)) 313 314 for i := range sl { 315 withSlice := sl[i].([]interface{}) 316 withs = append(withs, withSlice[1].(*With)) 317 } 318 319 return withs, nil 320} 321 322func makeWithKeyword(loc *Location, target, value interface{}) (interface{}, error) { 323 w := &With{ 324 Target: target.(*Term), 325 Value: value.(*Term), 326 } 327 return w.SetLocation(loc), nil 328} 329 330func makeExprTerm(loc *Location, lhs, rest interface{}) (interface{}, error) { 331 332 if rest == nil { 333 return lhs, nil 334 } 335 336 sl := rest.([]interface{}) 337 338 if len(sl) == 0 { 339 return lhs, nil 340 } 341 342 for i := range sl { 343 termSlice := sl[i].([]interface{}) 344 call := Call{ 345 termSlice[1].(*Term), 346 lhs.(*Term), 347 termSlice[3].(*Term), 348 } 349 lhs = NewTerm(call).SetLocation(loc) 350 } 351 352 return lhs, nil 353} 354 355func makeCall(loc *Location, operator, args interface{}) (interface{}, error) { 356 357 termSlice := args.([]*Term) 358 termOperator := operator.(*Term) 359 360 call := make(Call, len(termSlice)+1) 361 362 if _, ok := termOperator.Value.(Var); ok { 363 termOperator = RefTerm(termOperator).SetLocation(loc) 364 } 365 366 call[0] = termOperator 367 368 for i := 1; i < len(call); i++ { 369 call[i] = termSlice[i-1] 370 } 371 372 return NewTerm(call).SetLocation(loc), nil 373} 374 375func makeBraceEnclosedBody(loc *Location, body interface{}) (interface{}, error) { 376 if body != nil { 377 return body, nil 378 } 379 return NewBody(NewExpr(ObjectTerm().SetLocation(loc)).SetLocation(loc)), nil 380} 381 382func makeBody(head, tail interface{}, pos int) (interface{}, error) { 383 384 sl := tail.([]interface{}) 385 body := make(Body, len(sl)+1) 386 body[0] = head.(*Expr) 387 388 for i := 1; i < len(body); i++ { 389 body[i] = sl[i-1].([]interface{})[pos].(*Expr) 390 } 391 392 return body, nil 393} 394 395func makeExprTermList(head, tail interface{}) (interface{}, error) { 396 397 var terms []*Term 398 399 if head == nil { 400 return terms, nil 401 } 402 403 sl := tail.([]interface{}) 404 405 terms = make([]*Term, 0, len(sl)+1) 406 terms = append(terms, head.(*Term)) 407 408 for i := range sl { 409 termSlice := sl[i].([]interface{}) 410 terms = append(terms, termSlice[3].(*Term)) 411 } 412 413 return terms, nil 414} 415 416func makeExprTermPairList(head, tail interface{}) (interface{}, error) { 417 418 var terms [][2]*Term 419 420 if head == nil { 421 return terms, nil 422 } 423 424 sl := tail.([]interface{}) 425 426 terms = make([][2]*Term, 0, len(sl)+1) 427 terms = append(terms, head.([2]*Term)) 428 429 for i := range sl { 430 termSlice := sl[i].([]interface{}) 431 terms = append(terms, termSlice[3].([2]*Term)) 432 } 433 434 return terms, nil 435} 436 437func makeExprTermPair(key, value interface{}) (interface{}, error) { 438 return [2]*Term{key.(*Term), value.(*Term)}, nil 439} 440 441func makeInfixOperator(loc *Location, text []byte) (interface{}, error) { 442 op := string(text) 443 for _, b := range Builtins { 444 if string(b.Infix) == op { 445 op = string(b.Name) 446 } 447 } 448 operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) 449 return operator, nil 450} 451 452func makeArray(loc *Location, list interface{}) (interface{}, error) { 453 termSlice := list.([]*Term) 454 return ArrayTerm(termSlice...).SetLocation(loc), nil 455} 456 457func makeObject(loc *Location, list interface{}) (interface{}, error) { 458 termPairSlice := list.([][2]*Term) 459 return ObjectTerm(termPairSlice...).SetLocation(loc), nil 460} 461 462func makeSet(loc *Location, list interface{}) (interface{}, error) { 463 termSlice := list.([]*Term) 464 return SetTerm(termSlice...).SetLocation(loc), nil 465} 466 467func makeArrayComprehension(loc *Location, head, body interface{}) (interface{}, error) { 468 return ArrayComprehensionTerm(head.(*Term), body.(Body)).SetLocation(loc), nil 469} 470 471func makeSetComprehension(loc *Location, head, body interface{}) (interface{}, error) { 472 return SetComprehensionTerm(head.(*Term), body.(Body)).SetLocation(loc), nil 473} 474 475func makeObjectComprehension(loc *Location, head, body interface{}) (interface{}, error) { 476 pair := head.([2]*Term) 477 return ObjectComprehensionTerm(pair[0], pair[1], body.(Body)).SetLocation(loc), nil 478} 479 480func makeRef(loc *Location, head, rest interface{}) (interface{}, error) { 481 482 headTerm := head.(*Term) 483 ifaceSlice := rest.([]interface{}) 484 485 ref := make(Ref, len(ifaceSlice)+1) 486 ref[0] = headTerm 487 488 for i := 1; i < len(ref); i++ { 489 ref[i] = ifaceSlice[i-1].(*Term) 490 } 491 492 return NewTerm(ref).SetLocation(loc), nil 493} 494 495func makeRefOperandDot(loc *Location, val interface{}) (interface{}, error) { 496 return StringTerm(string(val.(*Term).Value.(Var))).SetLocation(loc), nil 497} 498 499func makeVar(loc *Location, text interface{}) (interface{}, error) { 500 str := string(text.([]byte)) 501 return VarTerm(str).SetLocation(loc), nil 502} 503 504func makeNumber(loc *Location, text interface{}) (interface{}, error) { 505 f, ok := new(big.Float).SetString(string(text.([]byte))) 506 if !ok { 507 // This indicates the grammar is out-of-sync with what the string 508 // representation of floating point numbers. This should not be 509 // possible. 510 panic("illegal value") 511 } 512 return NumberTerm(json.Number(f.String())).SetLocation(loc), nil 513} 514 515func makeString(loc *Location, text interface{}) (interface{}, error) { 516 var v string 517 err := json.Unmarshal(text.([]byte), &v) 518 return StringTerm(v).SetLocation(loc), err 519} 520 521func makeRawString(loc *Location, text interface{}) (interface{}, error) { 522 s := string(text.([]byte)) 523 s = s[1 : len(s)-1] // Trim surrounding quotes. 524 return StringTerm(s).SetLocation(loc), nil 525} 526 527func makeBool(loc *Location, text interface{}) (interface{}, error) { 528 var term *Term 529 if string(text.([]byte)) == "true" { 530 term = BooleanTerm(true) 531 } else { 532 term = BooleanTerm(false) 533 } 534 return term.SetLocation(loc), nil 535} 536 537func makeNull(loc *Location) (interface{}, error) { 538 return NullTerm().SetLocation(loc), nil 539} 540 541func makeComments(c *current, text interface{}) (interface{}, error) { 542 543 var buf bytes.Buffer 544 for _, x := range text.([]interface{}) { 545 buf.Write(x.([]byte)) 546 } 547 548 comment := NewComment(buf.Bytes()) 549 comment.Location = currentLocation(c) 550 comments := c.globalStore[commentsKey].([]*Comment) 551 comments = append(comments, comment) 552 c.globalStore[commentsKey] = comments 553 554 return comment, nil 555} 556 557func ifacesToBody(i interface{}, a ...interface{}) Body { 558 var buf Body 559 buf = append(buf, i.(*Expr)) 560 for _, s := range a { 561 expr := s.([]interface{})[3].(*Expr) 562 buf = append(buf, expr) 563 } 564 return buf 565} 566