{"componentChunkName":"component---src-templates-post-tsx","path":"/a-tour-of-implementing-tapl-in-scala","result":{"data":{"markdownRemark":{"html":"<p>Last week I implemented sub-type algorithms in Rust and put <a href=\"https://github.com/chengluyu/tapl-rust\" target=\"_blank\" rel=\"noopener noreferrer\">the source code on GitHub</a>. In this week, I rewrite the project with Scala, because I am going to work in Scala. This post is not a step-by-step explanation of the project, but more like a topic-based notes during the implementation.</p>\n<h1>Singleton Object</h1>\n<p>A newly created Scala project has code like this.</p>\n<div class=\"gatsby-highlight\" data-language=\"scala\"><pre class=\"language-scala\"><code class=\"language-scala\"><span class=\"token keyword\">object</span> Main <span class=\"token keyword\">extends</span> App <span class=\"token punctuation\">{</span>\n  println<span class=\"token punctuation\">(</span><span class=\"token string\">\"Hello, world!\"</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>I have several questions in my first glance.</p>\n<ul>\n<li>What the heck is <code class=\"language-text\">Main</code>? Is it an object, or a type (class)?</li>\n<li>Why and how could <code class=\"language-text\">Main</code> extend <code class=\"language-text\">App</code>?</li>\n<li>Why <code class=\"language-text\">println</code> can be placed in <code class=\"language-text\">Main</code>? Does <code class=\"language-text\">Main</code> works like a function?</li>\n</ul>\n<p>Here are my answers.</p>\n<ul>\n<li>\n<p><code class=\"language-text\">Main</code> is an object. It is categorized as a value. It is not a type. You can try this.</p>\n<div class=\"gatsby-highlight\" data-language=\"scala\"><pre class=\"language-scala\"><code class=\"language-scala\"><span class=\"token keyword\">def</span> test<span class=\"token punctuation\">(</span>main<span class=\"token operator\">:</span> Main<span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span> <span class=\"token comment\">// not found: type Main</span></code></pre></div>\n</li>\n<li>I think <code class=\"language-text\">Main</code> has a hidden and inaccessible type. Let’s call it <code class=\"language-text\">T</code>. So it actually means that <code class=\"language-text\">T</code> extends <code class=\"language-text\">App</code>. In this way, <code class=\"language-text\">Main</code> has everything in <code class=\"language-text\">App</code>.</li>\n<li>This is syntax inherited from classes, I think. Each class declaration is actually a constructor declaration (I think Kotlin learned from this). In the primary class constructor, people can put method declarations, statements and expressions.</li>\n</ul>\n<p>Another interesting yet familiar thing is <em>companion object</em>. It means you can create a singleton object called the same name of a class. I heard that static methods in Scala are mostly done in this way.</p>\n<h1>While Statements</h1>\n<p>I will make an REPL. So I need something like</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">while (true) {\n  line = readLine()\n  reply(line)\n}</code></pre></div>\n<p>Soon I found Scala is a expression-based language, so while expressions are typed. And they are typed to <code class=\"language-text\">Unit</code> since the halt problem. That’s okay.</p>\n<p>Then, how about break and continue? To my surprise, they are not included in the language. I read the Scala Book but I didn’t notice this point. I found <code class=\"language-text\">scala.util.control.Breaks</code>, but it seems be implemented with exceptions.</p>\n<p><a href=\"https://www.scala-lang.org/api/2.13.3/scala/util/control/Breaks.html\" target=\"_blank\" rel=\"noopener noreferrer\">Scala Standard Library 2.13.3 - scala.util.control.Breaks</a></p>\n<p>So I put the while expression in a method and use return instead. Here is the skeleton of the REPL.</p>\n<div class=\"gatsby-highlight\" data-language=\"scala\"><pre class=\"language-scala\"><code class=\"language-scala\"><span class=\"token keyword\">object</span> Main <span class=\"token keyword\">extends</span> App <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">val</span> context <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> Context<span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">def</span> repl<span class=\"token operator\">:</span> <span class=\"token builtin\">Unit</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">val</span> command <span class=\"token operator\">=</span> readLine<span class=\"token punctuation\">(</span><span class=\"token string\">\"> \"</span><span class=\"token punctuation\">)</span>\n    command <span class=\"token keyword\">match</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">case</span> <span class=\"token string\">\"exit\"</span> <span class=\"token keyword\">=></span> <span class=\"token keyword\">return</span>\n      <span class=\"token keyword\">case</span> command <span class=\"token keyword\">=></span> println<span class=\"token punctuation\">(</span>command<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  println<span class=\"token punctuation\">(</span><span class=\"token string\">\"Welcome to TAPL Scala!\"</span><span class=\"token punctuation\">)</span>\n  repl\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h1>Deal with <code class=\"language-text\">Option</code></h1>\n<p>I’m dealing with <code class=\"language-text\">Option</code> in Scala. There are few ways I know so far.</p>\n<ul>\n<li>Pattern matching. <code class=\"language-text\">x match { Some(y) => z None => a }</code>.</li>\n<li>Methods from <code class=\"language-text\">Iterable</code>. Because <code class=\"language-text\">Option</code> is actually a container of a single value, so what people can do with <code class=\"language-text\">Iterable</code> also works here.</li>\n<li>Some specific methods. Like <code class=\"language-text\">getOrElse</code>, <code class=\"language-text\">isEmpty</code>, <code class=\"language-text\">isDefined</code>.</li>\n</ul>\n<h1>Derive with Exceptions</h1>\n<p>When type inference fails, we need to handle errors. In my Rust implementation, errors are contained by <code class=\"language-text\">Result&lt;TermType, String></code>. Rust offers some syntactic sugars dealing with them, for example, if the return type of surrounding function is also the same <code class=\"language-text\">Result</code> type, appending an <code class=\"language-text\">?</code> to the expression will return the error part if it is an <code class=\"language-text\">Err</code>, just like the <code class=\"language-text\">lift</code> in <code class=\"language-text\">Monad</code>.</p>\n<p>In Scala, we can use exception, just like how we do it in Java. Therefore, we need custom errors. I found a solution on StackOverflow: <a href=\"https://stackoverflow.com/questions/38243530/custom-exception-in-scala\" target=\"_blank\" rel=\"noopener noreferrer\">Custom Exception in scala</a>.</p>\n<h1>Operator Overloading</h1>\n<p>Because I was learning the book <em>Types and Programming Languages</em>. I wanted to define <code class=\"language-text\">&lt;:</code> as the “is subtype of” operator. Soon I found this is impossible because <code class=\"language-text\">&lt;:</code> is reserved as the sub-type operator. Therefore, I chose <code class=\"language-text\">&lt;::</code> as the operator.</p>\n<p>Operator overloading is easy in Scala. The syntax does not differ from defining functions.</p>\n<div class=\"gatsby-highlight\" data-language=\"scala\"><pre class=\"language-scala\"><code class=\"language-scala\"><span class=\"token keyword\">trait</span> Type <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">def</span> toString<span class=\"token operator\">:</span> <span class=\"token builtin\">String</span>\n  <span class=\"token keyword\">def</span> <span class=\"token operator\">&lt;</span><span class=\"token operator\">::</span><span class=\"token punctuation\">(</span>that<span class=\"token operator\">:</span> Type<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token builtin\">Boolean</span>\n  <span class=\"token keyword\">def</span> <span class=\"token operator\">==</span><span class=\"token punctuation\">(</span>other<span class=\"token operator\">:</span> Type<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> <span class=\"token builtin\">Boolean</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>But, I found another problem. When I test the expression <code class=\"language-text\">if true then {} else { a: 0 }</code>, the result type is <code class=\"language-text\">Record { a: Int }</code>. What the heck? I thought I messed up some order, for example, reversing the order of if branches or something like that. But the logs indicate that <code class=\"language-text\">a &lt;:: b</code> is actually equivalent to <code class=\"language-text\">b.&lt;::(a)</code>. Hmm, interesting.</p>\n<p>I started searching in Scala documentation and Scala Book, but they told me nothing. Soon I found the answer in Scala specifications. I like reading specifications, because they are mostly well-structured so I can locate what I want immediately. I remembered I read ECMA-262 for thousands times because it is the only document telling me what’s really happening in the execution context.</p>\n<p>Okay, let’s back to the topic. Here is what I found from this page: <a href=\"https://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#infix-operations\" target=\"_blank\" rel=\"noopener noreferrer\">Expressions</a>.</p>\n<blockquote>\n<p>The <em>associativity</em> of an operator is determined by the operator's last character. Operators ending in a colon `:' are right-associative. All other operators are left-associative.</p>\n</blockquote>\n<p>Because I don’t want to change my code too much, I just rename the operator <code class=\"language-text\">:&lt;</code>. It looks like an unhappy face. Just like my mood. (I’m just joking.) I have to manually rename the operator because Metals says it will break my code. Even if I had replace all occurrences of infix notations with member function notations.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6e648d3348a0815577c626500a13e10b/6da96/1.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 29.72972972972973%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA3klEQVQY01VQbZKFIAzj/ld7O+Mq7tPnBwIq4F4i2zALoz8yLaVNmio3zTC6h/U7/A3OeRzHiX0/aix1a12OIQRMMs+/8wwZKpkNpuvQCmnf/6BpvqElJ4ZhqHnB+z2g6zRery98PhPW1cALeRFWZ7xgRJFNWus6SHLWmqbJ9XEc0bbdv9AIw0UE1/WLGFOFckIWZNVlXbFtVqy42kx1WqJFqvPNrWiXRCldYjs+oKz1uZEE87xkLMuaa0QUBxykOmPJC0FK6fFW+xHk2P52bFePTsQYH5buIDkXKsTEHx6YscJZKFYfAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Cannot rename the operator.\"\n        title=\"Cannot rename the operator.\"\n        src=\"/static/6e648d3348a0815577c626500a13e10b/fcda8/1.png\"\n        srcset=\"/static/6e648d3348a0815577c626500a13e10b/12f09/1.png 148w,\n/static/6e648d3348a0815577c626500a13e10b/e4a3f/1.png 295w,\n/static/6e648d3348a0815577c626500a13e10b/fcda8/1.png 590w,\n/static/6e648d3348a0815577c626500a13e10b/efc66/1.png 885w,\n/static/6e648d3348a0815577c626500a13e10b/6da96/1.png 922w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/548f331fdf8b55b1857fd4fb32cb1bdf/32056/2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 82.43243243243244%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACgUlEQVQ4y3VU23baMBDk/z+ppz1JgJAQbsYXYfluczM2xEDS5+msOHbSpH0YtJJWszu7i3uvrw3yvICrVvCI1cpHEITwPAXLWpo78TkeTzidXv9Ce3ZbG2P35Keqj1hHMdJAoyhybLd77HYlyXKue+Nc0+co4ONvEI5DibqqSEin+u0d1c9fqKwJktUDMjVE4t4jtn4w0BSZ/4hUDZB490i9PiL7J6p9gfP5DU3T4HL9jUxPsCvCW4aCAzOJwghpmiGOY4RhyDVCnGyw0htkWYYkSZESWZYjoqI4Tjq0PB1heai6+vm+5hqxjh60zuB4Be+0uVOs8+0+ZNAIjuPSDjr5H4TlwTiIc0ssJLa9NLZl7/nYM82Svet6xtdxHBOkbdCHZBJK6iJLHghElkD5a+ggNwFbiXIvq9aBKdM3wpKwbMdkJ5FbOZLl0tkaW2vdZSd+tm3Tdk0SH4RHjsL1HYe7O2wtC34UmeZIZMFms+WDW+bSLFklmBA0zdnM6Oe5JOEJFTe1Utiys8pPmCFJSSwPZbClq20JbsQJDmyiENRfZvM22FWNkhub6XtqR4kxi++a2oiktkkiW+QK8Rtn93K5GkiWkq2RvC7W5mFCp8V8gfnMwtPTGLPpFLOZwvPY5dnM3E1eJjyb826Gl/ELz+eYTqZmNkMGzKmkV5AwI6FmI4aDIcbPY0zoNOj38Tiy8DBY8Jz2cGQe9x9oP44wEF+SjkZP8KmgI2wlS0183zdypLPa96BWG/jBDtfrxUg8ny+dzM84UXLbnJ4UUsikuNIAKXia8uvjcR5DSokylPvSdPufH4YvMBm2HZNaymwpFWCxXNOWhqzM+LR/r3Y8/oc/yZmFxFkhwlQAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Find usage of the operator.\"\n        title=\"Find usage of the operator.\"\n        src=\"/static/548f331fdf8b55b1857fd4fb32cb1bdf/fcda8/2.png\"\n        srcset=\"/static/548f331fdf8b55b1857fd4fb32cb1bdf/12f09/2.png 148w,\n/static/548f331fdf8b55b1857fd4fb32cb1bdf/e4a3f/2.png 295w,\n/static/548f331fdf8b55b1857fd4fb32cb1bdf/fcda8/2.png 590w,\n/static/548f331fdf8b55b1857fd4fb32cb1bdf/32056/2.png 602w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Finally, everything about operator overloading is done.</p>\n<h1>Parsing Rules</h1>\n<p>In the Rust implementation, I use LALRPOP, which generates Rust code at the build time from a DSL. Because it uses LALR, it can inform me of ambiguity when there is a one. It even show you a nice diagram in case you don’t know what it is talking about.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 590px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/4c53614dc53e7a0dd8077ea0e9cba195/f43e4/3.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABp0lEQVQoz31S13LCQAz0TySQQjHgbnA32AZTEtInk8n//8tGK2JmwkMehOTjtLfalTHxI+ye35HWLbZPb4iWDcrNAS+f32gOz8iaLfL1DtX+iHleYbV91Pr48YX2+Ipa6kXZYBrEsKMcxsDy4cYF0qqVP2oFDKUxzFfw0xKzeYqxO8ckiDByQoykNr0F7mYerkcz9MYW+qZ9DoMHvBgIQFJtlGmx2SswX+YZY9k+wF5kKNuDfLcYSg8BbibOnzB6cugIVbKLl2vNBFVwaYxXGx2Hj7JhIvWJnaXfl6AGD26nLtYPL6LZExIByJudZgJm9VZrxlhGpY6WMOVkl+wUkD98kTpypHvLw8D2JYJzDJlFa2p3L5kEOmZ9Apmn3O8Y2lGmTnYa0lmyY53Wp7raHeGJSXTZ/o8hAemWI6BOnINrNAsTmJKnYaya0eFivRfXl5gXtTif4Go41T5q2dVXEjqyJatB3SJxlaO7SaFGBdkKntRcIQJ5SSm50jumv9A7fJy6dn0GHeTeUfxIXCZIKWujpvyO3y03l5ijkyG1paYjNzxPxOl+AA62Mje4p39IAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Ambiguity diagram displayed from LALRPOP\"\n        title=\"Ambiguity diagram displayed from LALRPOP\"\n        src=\"/static/4c53614dc53e7a0dd8077ea0e9cba195/fcda8/3.png\"\n        srcset=\"/static/4c53614dc53e7a0dd8077ea0e9cba195/12f09/3.png 148w,\n/static/4c53614dc53e7a0dd8077ea0e9cba195/e4a3f/3.png 295w,\n/static/4c53614dc53e7a0dd8077ea0e9cba195/fcda8/3.png 590w,\n/static/4c53614dc53e7a0dd8077ea0e9cba195/efc66/3.png 885w,\n/static/4c53614dc53e7a0dd8077ea0e9cba195/f43e4/3.png 1120w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Fastparse is handy. I can write a parser in less than 20 lines of code. But it is based on backtracking strategies, which means sometimes I find the problem at the runtime.</p>\n<p>Here is my grammar without any modification.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">term          -> apply\n              |  project\n              |  true\n              |  false\n              |  int\n              |  if\n              |  abstract\n              |  variable\n              |  record\n              |  parenthesized\napply         -> term \"(\" term \")\"\nproject       -> term \".\" ident\ntrue          -> \"true\"\nfalse         -> \"false\"\nint           -> [0-9]+\nif            -> \"if\" term \"then\" term \"else\" term\nabstract      -> \"(\" ident \":\" type \")\" \"=>\" term\nvariable      -> ident\nrecord        -> \"{\" entry (\",\" entry)* \"}\" where entry -> ident \":\" term\nparenthesized -> \"(\" term \")\"</code></pre></div>\n<p>There are some obvious left-recursive rules: <code class=\"language-text\">apply</code> and <code class=\"language-text\">project</code>, so we can make them as a postfix rule. Replace the first 3 rules with these 4 rules.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">term          -> term' (apply-tail | project-tail)*\nterm'         -> true\n              |  false\n              |  int\n              |  if\n              |  abstract\n              |  variable\n              |  record\n              |  parenthesized\napply-tail    -> \"(\" term \")\"\nproject-tail  -> \".\" ident</code></pre></div>\n<p>Then we will spot some “dangling-else” problems (not the <code class=\"language-text\">else</code> in the <code class=\"language-text\">if</code> rule because <code class=\"language-text\">else</code> clause is required). They are <code class=\"language-text\">if</code> and <code class=\"language-text\">abstract</code>. For example, <code class=\"language-text\">(x: Int) => x.y</code> can be interpreted into either <code class=\"language-text\">((x: Int) => x).y</code> or <code class=\"language-text\">(x: Int) => (x.y</code>. The solution is to give <code class=\"language-text\">apply-tail</code> and <code class=\"language-text\">project-tail</code> higher binding weights than <code class=\"language-text\">if</code> and <code class=\"language-text\">abstract</code> have.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">term    -> simple (apply-tail | project-tail)* | complex\nsimple  -> true | false | int | variable | record | parenthesized\ncomplex -> if | abstract</code></pre></div>\n<p>In the new rules above, <code class=\"language-text\">term</code> is either a simple term (terms without “dangling-else” problems) with any number of tails, or a complex term with no tails. By far the parser is almost done. However, I stepped into other two rabbit holes.</p>\n<ul>\n<li>Should cut (operator <code class=\"language-text\">~</code>)at appropriate position, or the parser might fail even if your grammar is correct! To cut is to tell the parser never look back.</li>\n<li>When using whitespace consumers, remember to parse tokens with <code class=\"language-text\">repX</code> rather than <code class=\"language-text\">rep</code>. For example, I spent a whole hour on debugging <code class=\"language-text\">ident = CharIn(\"a-zA-Z\").rep(1)</code>!</li>\n</ul>\n<h2>Conclusion</h2>\n<p>Finally, I had finish the project and uploaded to GitHub. You can check it out <a href=\"https://github.com/chengluyu/tapl-scala\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</p>\n<p>Besides, I also want to address some off-topic discoveries about language servers. I’m writing Scala with Visual Studio Code. I felt that the Scala language server is very stable and ergonomic. It could expand complicated macro in seconds. It made the development smoother than I had expected.</p>\n<p>Before I write Scala in Visual Studio Code, I often use Rust and TypeScript.</p>\n<p>The TypeScript language server works pretty well. But there are still bunch of times when it stuck because there are too many type assertions and sub-types, especially when I was writing a large tree visitor with Babel. Rust language server sometimes are lazy to check ownership so everything seems fine in the editor but you get bunch of errors when compiling. There are also times the language server failed to expanded macro from newly installed crates.</p>\n<p>Anyway, I’m not complaining about the language servers of TypeScript and Rust. They are also very great.</p>","frontmatter":{"title":"A Tour of Implementing TAPL in Scala","date":"July 01, 2021","tags":["scala"],"language":"en"}},"site":{"siteMetadata":{"title":"Luyu Cheng"}}},"pageContext":{"id":"392a13f5-2c9b-5eb0-8b7f-77e4694fce47"}},"staticQueryHashes":["3649515864","63159454","684267432"]}