{"action":"created","comment":{"url":"https://api.github.com/repos/istio/mixer/pulls/comments/100857735","pull_request_review_id":21574025,"id":100857735,"diff_hunk":"@@ -0,0 +1,365 @@\n+// Copyright 2017 Google Inc.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+package expr\n+\n+import (\n+\t\"bytes\"\n+\t\"fmt\"\n+\t\"go/ast\"\n+\t\"go/parser\"\n+\t\"go/token\"\n+\t\"strconv\"\n+\t\"strings\"\n+\n+\t\"github.com/golang/glog\"\n+\n+\tconfig \"istio.io/api/mixer/v1/config/descriptor\"\n+\t\"istio.io/mixer/pkg/attribute\"\n+)\n+\n+// This private variable is an extract from go/token\n+// it maps expression related token to its names\n+var tMap = map[token.Token]string{\n+\ttoken.ILLEGAL: \"ILLEGAL\",\n+\n+\ttoken.EOF:     \"EOF\",\n+\ttoken.COMMENT: \"COMMENT\",\n+\n+\ttoken.IDENT:  \"IDENT\",\n+\ttoken.INT:    \"INT\",\n+\ttoken.FLOAT:  \"FLOAT\",\n+\ttoken.IMAG:   \"IMAG\",\n+\ttoken.CHAR:   \"CHAR\",\n+\ttoken.STRING: \"STRING\",\n+\n+\ttoken.ADD: \"ADD\",\n+\ttoken.SUB: \"SUB\",\n+\ttoken.MUL: \"MUL\",\n+\ttoken.QUO: \"QUO\",\n+\ttoken.REM: \"REM\",\n+\n+\ttoken.AND:  \"AND\",\n+\ttoken.OR:   \"OR\",\n+\ttoken.XOR:  \"XOR\",\n+\ttoken.LAND: \"LAND\",\n+\ttoken.LOR:  \"LOR\",\n+\n+\ttoken.EQL: \"EQ\",\n+\ttoken.LSS: \"LT\",\n+\ttoken.GTR: \"GT\",\n+\ttoken.NOT: \"NOT\",\n+\n+\ttoken.NEQ: \"NEQ\",\n+\ttoken.LEQ: \"LEQ\",\n+\ttoken.GEQ: \"GEQ\",\n+\n+\ttoken.LBRACK: \"INDEX\",\n+}\n+\n+var typeMap = map[token.Token]config.ValueType{\n+\ttoken.INT:    config.INT64,\n+\ttoken.FLOAT:  config.DOUBLE,\n+\ttoken.CHAR:   config.STRING,\n+\ttoken.STRING: config.STRING,\n+}\n+\n+// Expression is a simplified expression AST\n+type Expression struct {\n+\t// Oneof the following\n+\tConst *Constant\n+\tVar   *Variable\n+\tFn    *Function\n+}\n+\n+// Eval evaluates the expression given an attribute bag and a function map.\n+func (e *Expression) Eval(attrs attribute.Bag, fMap map[string]Func) (interface{}, error) {\n+\tif e.Const != nil {\n+\t\treturn e.Const.TypedValue, nil\n+\t}\n+\tif e.Var != nil {\n+\t\tv, ok := attribute.Value(attrs, e.Var.Name)\n+\t\tif !ok {\n+\t\t\treturn nil, fmt.Errorf(\"unresolved attribute %s\", e.Var.Name)\n+\t\t}\n+\t\treturn v, nil\n+\t}\n+\t// may panic\n+\treturn e.Fn.Eval(attrs, fMap)\n+}\n+\n+// String produces postfix version with all operators converted to function names\n+func (e *Expression) String() string {\n+\tif e.Const != nil {\n+\t\treturn e.Const.String()\n+\t}\n+\tif e.Var != nil {\n+\t\treturn e.Var.String()\n+\t}\n+\tif e.Fn != nil {\n+\t\treturn e.Fn.String()\n+\t}\n+\treturn \"<nil>\"\n+}\n+\n+// newConstant creates a new constant of given type.\n+// It also stores a typed form of the constant.\n+func newConstant(v string, vType config.ValueType) (*Constant, error) {\n+\tvar typedVal interface{}\n+\tvar err error\n+\tswitch vType {\n+\tcase config.INT64:\n+\t\tif typedVal, err = strconv.ParseInt(v, 10, 64); err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\tcase config.DOUBLE:\n+\t\tif typedVal, err = strconv.ParseFloat(v, 64); err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\tdefault: // string\n+\t\tif typedVal, err = strconv.Unquote(v); err != nil {\n+\t\t\treturn nil, err\n+\t\t}\n+\t}\n+\treturn &Constant{Value: v, Kind: vType, TypedValue: typedVal}, nil\n+}\n+\n+// Constant models a typed constant.\n+type Constant struct {","path":"pkg/expr/expr.go","position":139,"original_position":139,"commit_id":"42999316555179228f7a7169432b1650a9f1441e","original_commit_id":"42999316555179228f7a7169432b1650a9f1441e","user":{"login":"ZackButcher","id":1923135,"avatar_url":"https://avatars.githubusercontent.com/u/1923135?v=3","gravatar_id":"","url":"https://api.github.com/users/ZackButcher","html_url":"https://github.com/ZackButcher","followers_url":"https://api.github.com/users/ZackButcher/followers","following_url":"https://api.github.com/users/ZackButcher/following{/other_user}","gists_url":"https://api.github.com/users/ZackButcher/gists{/gist_id}","starred_url":"https://api.github.com/users/ZackButcher/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ZackButcher/subscriptions","organizations_url":"https://api.github.com/users/ZackButcher/orgs","repos_url":"https://api.github.com/users/ZackButcher/repos","events_url":"https://api.github.com/users/ZackButcher/events{/privacy}","received_events_url":"https://api.github.com/users/ZackButcher/received_events","type":"User","site_admin":false},"body":"The field's names feel off here; I think it'd make more sense as:\r\n\r\n    struct Constant struct {\r\n        Str String\r\n        Value interface{}\r\n        Type config.ValueType\r\n    }","created_at":"2017-02-13T18:07:33Z","updated_at":"2017-02-13T18:26:57Z","html_url":"https://github.com/istio/mixer/pull/255#discussion_r100857735","pull_request_url":"https://api.github.com/repos/istio/mixer/pulls/255","_links":{"self":{"href":"https://api.github.com/repos/istio/mixer/pulls/comments/100857735"},"html":{"href":"https://github.com/istio/mixer/pull/255#discussion_r100857735"},"pull_request":{"href":"https://api.github.com/repos/istio/mixer/pulls/255"}}},"pull_request":{"url":"https://api.github.com/repos/istio/mixer/pulls/255","id":105734623,"html_url":"https://github.com/istio/mixer/pull/255","diff_url":"https://github.com/istio/mixer/pull/255.diff","patch_url":"https://github.com/istio/mixer/pull/255.patch","issue_url":"https://api.github.com/repos/istio/mixer/issues/255","number":255,"state":"open","locked":false,"title":"Expression language","user":{"login":"mandarjog","id":800375,"avatar_url":"https://avatars.githubusercontent.com/u/800375?v=3","gravatar_id":"","url":"https://api.github.com/users/mandarjog","html_url":"https://github.com/mandarjog","followers_url":"https://api.github.com/users/mandarjog/followers","following_url":"https://api.github.com/users/mandarjog/following{/other_user}","gists_url":"https://api.github.com/users/mandarjog/gists{/gist_id}","starred_url":"https://api.github.com/users/mandarjog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mandarjog/subscriptions","organizations_url":"https://api.github.com/users/mandarjog/orgs","repos_url":"https://api.github.com/users/mandarjog/repos","events_url":"https://api.github.com/users/mandarjog/events{/privacy}","received_events_url":"https://api.github.com/users/mandarjog/received_events","type":"User","site_admin":false},"body":"Introducing expression language.\r\n\r\nFront end uses golang parser.\r\nInternal AST only has 3 nodes: `variables, constants, functions`\r\nAll of them are directly or indirectly typed. All operators are functions. \r\n`substring(a, 5) == \"abc\"  --> EQ(substring($a, 5), \"abc\")`\r\n\r\nSupports following types of expressions.  Supports predicates and other expression in a uniform way.\r\n\r\nPredicates   returns bool\r\n```\r\nservice.name == \"*.ns1.cluster\" && service.user == \"admin\"\r\nrequest.user == \"user1\"\r\n(x == 20 && y == 10) || x == 30\r\n\r\nrequest.header[\"X-FORWARDED-HOST\"] == \"aaa\"`\r\n```\r\nMapping Expressions\r\n```\r\nrequest.user2| request.user3 | \"user1\"     --> returns string\r\n`request.size| 200`                                    --> returns int\r\n```\r\n\r\nFunctions are implemented using `Func` interface\r\n```\r\ntype Func interface {\r\n        // Name uniquely identified the function.\r\n        Name() string\r\n        // ReturnType specifies the return type of this function.\r\n        ReturnType() config.ValueType\r\n        // ArgTypes specifies the argument types in order expected by the function.\r\n        ArgTypes() []config.ValueType\r\n        // NullArgs specifies if the function accepts null args\r\n        NullArgs() bool\r\n        // Call performs the function call. It is guaranteed\r\n        // that call will be made with correct types and arity.\r\n        // may panic.\r\n        Call([]interface{}) interface{}\r\n}\r\n```\r\n\r\nNotes:\r\nserver.go still does not use this Expression evaluator.\r\n\r\nTODO:\r\n1. Implement config type checking.\r\n    All variables, constants and functions are typed.\r\n\r\n\r\n---\r\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/istio/mixer/255)\r\n<!-- Reviewable:end -->\n\n<!-- Reviewable:start -->\n---\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/istio/mixer/255)\n<!-- Reviewable:end -->\n","created_at":"2017-02-11T01:26:39Z","updated_at":"2017-02-13T18:26:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f018163c648e4c3380ab5cbc2dd066db74ed5371","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/istio/mixer/pulls/255/commits","review_comments_url":"https://api.github.com/repos/istio/mixer/pulls/255/comments","review_comment_url":"https://api.github.com/repos/istio/mixer/pulls/comments{/number}","comments_url":"https://api.github.com/repos/istio/mixer/issues/255/comments","statuses_url":"https://api.github.com/repos/istio/mixer/statuses/42999316555179228f7a7169432b1650a9f1441e","head":{"label":"mandarjog:new_expr","ref":"new_expr","sha":"42999316555179228f7a7169432b1650a9f1441e","user":{"login":"mandarjog","id":800375,"avatar_url":"https://avatars.githubusercontent.com/u/800375?v=3","gravatar_id":"","url":"https://api.github.com/users/mandarjog","html_url":"https://github.com/mandarjog","followers_url":"https://api.github.com/users/mandarjog/followers","following_url":"https://api.github.com/users/mandarjog/following{/other_user}","gists_url":"https://api.github.com/users/mandarjog/gists{/gist_id}","starred_url":"https://api.github.com/users/mandarjog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mandarjog/subscriptions","organizations_url":"https://api.github.com/users/mandarjog/orgs","repos_url":"https://api.github.com/users/mandarjog/repos","events_url":"https://api.github.com/users/mandarjog/events{/privacy}","received_events_url":"https://api.github.com/users/mandarjog/received_events","type":"User","site_admin":false},"repo":{"id":75396439,"name":"mixer","full_name":"mandarjog/mixer","owner":{"login":"mandarjog","id":800375,"avatar_url":"https://avatars.githubusercontent.com/u/800375?v=3","gravatar_id":"","url":"https://api.github.com/users/mandarjog","html_url":"https://github.com/mandarjog","followers_url":"https://api.github.com/users/mandarjog/followers","following_url":"https://api.github.com/users/mandarjog/following{/other_user}","gists_url":"https://api.github.com/users/mandarjog/gists{/gist_id}","starred_url":"https://api.github.com/users/mandarjog/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mandarjog/subscriptions","organizations_url":"https://api.github.com/users/mandarjog/orgs","repos_url":"https://api.github.com/users/mandarjog/repos","events_url":"https://api.github.com/users/mandarjog/events{/privacy}","received_events_url":"https://api.github.com/users/mandarjog/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mandarjog/mixer","description":"The Istio mixer and its adapters.","fork":true,"url":"https://api.github.com/repos/mandarjog/mixer","forks_url":"https://api.github.com/repos/mandarjog/mixer/forks","keys_url":"https://api.github.com/repos/mandarjog/mixer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mandarjog/mixer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mandarjog/mixer/teams","hooks_url":"https://api.github.com/repos/mandarjog/mixer/hooks","issue_events_url":"https://api.github.com/repos/mandarjog/mixer/issues/events{/number}","events_url":"https://api.github.com/repos/mandarjog/mixer/events","assignees_url":"https://api.github.com/repos/mandarjog/mixer/assignees{/user}","branches_url":"https://api.github.com/repos/mandarjog/mixer/branches{/branch}","tags_url":"https://api.github.com/repos/mandarjog/mixer/tags","blobs_url":"https://api.github.com/repos/mandarjog/mixer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mandarjog/mixer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mandarjog/mixer/git/refs{/sha}","trees_url":"https://api.github.com/repos/mandarjog/mixer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mandarjog/mixer/statuses/{sha}","languages_url":"https://api.github.com/repos/mandarjog/mixer/languages","stargazers_url":"https://api.github.com/repos/mandarjog/mixer/stargazers","contributors_url":"https://api.github.com/repos/mandarjog/mixer/contributors","subscribers_url":"https://api.github.com/repos/mandarjog/mixer/subscribers","subscription_url":"https://api.github.com/repos/mandarjog/mixer/subscription","commits_url":"https://api.github.com/repos/mandarjog/mixer/commits{/sha}","git_commits_url":"https://api.github.com/repos/mandarjog/mixer/git/commits{/sha}","comments_url":"https://api.github.com/repos/mandarjog/mixer/comments{/number}","issue_comment_url":"https://api.github.com/repos/mandarjog/mixer/issues/comments{/number}","contents_url":"https://api.github.com/repos/mandarjog/mixer/contents/{+path}","compare_url":"https://api.github.com/repos/mandarjog/mixer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mandarjog/mixer/merges","archive_url":"https://api.github.com/repos/mandarjog/mixer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mandarjog/mixer/downloads","issues_url":"https://api.github.com/repos/mandarjog/mixer/issues{/number}","pulls_url":"https://api.github.com/repos/mandarjog/mixer/pulls{/number}","milestones_url":"https://api.github.com/repos/mandarjog/mixer/milestones{/number}","notifications_url":"https://api.github.com/repos/mandarjog/mixer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mandarjog/mixer/labels{/name}","releases_url":"https://api.github.com/repos/mandarjog/mixer/releases{/id}","deployments_url":"https://api.github.com/repos/mandarjog/mixer/deployments","created_at":"2016-12-02T13:06:30Z","updated_at":"2016-12-02T13:06:32Z","pushed_at":"2017-02-13T04:10:57Z","git_url":"git://github.com/mandarjog/mixer.git","ssh_url":"git@github.com:mandarjog/mixer.git","clone_url":"https://github.com/mandarjog/mixer.git","svn_url":"https://github.com/mandarjog/mixer","homepage":null,"size":12270,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"istio:master","ref":"master","sha":"f69e0deaedcf40225f8e03183fa9c1f9b9dfec4f","user":{"login":"istio","id":23534644,"avatar_url":"https://avatars.githubusercontent.com/u/23534644?v=3","gravatar_id":"","url":"https://api.github.com/users/istio","html_url":"https://github.com/istio","followers_url":"https://api.github.com/users/istio/followers","following_url":"https://api.github.com/users/istio/following{/other_user}","gists_url":"https://api.github.com/users/istio/gists{/gist_id}","starred_url":"https://api.github.com/users/istio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/istio/subscriptions","organizations_url":"https://api.github.com/users/istio/orgs","repos_url":"https://api.github.com/users/istio/repos","events_url":"https://api.github.com/users/istio/events{/privacy}","received_events_url":"https://api.github.com/users/istio/received_events","type":"Organization","site_admin":false},"repo":{"id":74177509,"name":"mixer","full_name":"istio/mixer","owner":{"login":"istio","id":23534644,"avatar_url":"https://avatars.githubusercontent.com/u/23534644?v=3","gravatar_id":"","url":"https://api.github.com/users/istio","html_url":"https://github.com/istio","followers_url":"https://api.github.com/users/istio/followers","following_url":"https://api.github.com/users/istio/following{/other_user}","gists_url":"https://api.github.com/users/istio/gists{/gist_id}","starred_url":"https://api.github.com/users/istio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/istio/subscriptions","organizations_url":"https://api.github.com/users/istio/orgs","repos_url":"https://api.github.com/users/istio/repos","events_url":"https://api.github.com/users/istio/events{/privacy}","received_events_url":"https://api.github.com/users/istio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/istio/mixer","description":"The Istio mixer and its adapters.","fork":false,"url":"https://api.github.com/repos/istio/mixer","forks_url":"https://api.github.com/repos/istio/mixer/forks","keys_url":"https://api.github.com/repos/istio/mixer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/istio/mixer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/istio/mixer/teams","hooks_url":"https://api.github.com/repos/istio/mixer/hooks","issue_events_url":"https://api.github.com/repos/istio/mixer/issues/events{/number}","events_url":"https://api.github.com/repos/istio/mixer/events","assignees_url":"https://api.github.com/repos/istio/mixer/assignees{/user}","branches_url":"https://api.github.com/repos/istio/mixer/branches{/branch}","tags_url":"https://api.github.com/repos/istio/mixer/tags","blobs_url":"https://api.github.com/repos/istio/mixer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/istio/mixer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/istio/mixer/git/refs{/sha}","trees_url":"https://api.github.com/repos/istio/mixer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/istio/mixer/statuses/{sha}","languages_url":"https://api.github.com/repos/istio/mixer/languages","stargazers_url":"https://api.github.com/repos/istio/mixer/stargazers","contributors_url":"https://api.github.com/repos/istio/mixer/contributors","subscribers_url":"https://api.github.com/repos/istio/mixer/subscribers","subscription_url":"https://api.github.com/repos/istio/mixer/subscription","commits_url":"https://api.github.com/repos/istio/mixer/commits{/sha}","git_commits_url":"https://api.github.com/repos/istio/mixer/git/commits{/sha}","comments_url":"https://api.github.com/repos/istio/mixer/comments{/number}","issue_comment_url":"https://api.github.com/repos/istio/mixer/issues/comments{/number}","contents_url":"https://api.github.com/repos/istio/mixer/contents/{+path}","compare_url":"https://api.github.com/repos/istio/mixer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/istio/mixer/merges","archive_url":"https://api.github.com/repos/istio/mixer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/istio/mixer/downloads","issues_url":"https://api.github.com/repos/istio/mixer/issues{/number}","pulls_url":"https://api.github.com/repos/istio/mixer/pulls{/number}","milestones_url":"https://api.github.com/repos/istio/mixer/milestones{/number}","notifications_url":"https://api.github.com/repos/istio/mixer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/istio/mixer/labels{/name}","releases_url":"https://api.github.com/repos/istio/mixer/releases{/id}","deployments_url":"https://api.github.com/repos/istio/mixer/deployments","created_at":"2016-11-19T00:40:17Z","updated_at":"2017-02-10T00:51:32Z","pushed_at":"2017-02-13T04:11:04Z","git_url":"git://github.com/istio/mixer.git","ssh_url":"git@github.com:istio/mixer.git","clone_url":"https://github.com/istio/mixer.git","svn_url":"https://github.com/istio/mixer","homepage":null,"size":12985,"stargazers_count":11,"watchers_count":11,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":18,"mirror_url":null,"open_issues_count":36,"forks":18,"open_issues":36,"watchers":11,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/istio/mixer/pulls/255"},"html":{"href":"https://github.com/istio/mixer/pull/255"},"issue":{"href":"https://api.github.com/repos/istio/mixer/issues/255"},"comments":{"href":"https://api.github.com/repos/istio/mixer/issues/255/comments"},"review_comments":{"href":"https://api.github.com/repos/istio/mixer/pulls/255/comments"},"review_comment":{"href":"https://api.github.com/repos/istio/mixer/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/istio/mixer/pulls/255/commits"},"statuses":{"href":"https://api.github.com/repos/istio/mixer/statuses/42999316555179228f7a7169432b1650a9f1441e"}}}}
{"actor":{"display_login":"ZackButcher"}}